Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/Common/CollapsingPlatform.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: CollapsingPlatform Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectCollapsingPlatform *CollapsingPlatform;
11
12
void CollapsingPlatform_Update(void)
13
{
14
RSDK_THIS(CollapsingPlatform);
15
16
self->visible = false;
17
if (DebugMode)
18
self->visible = DebugMode->debugActive;
19
20
bool32 runState = false;
21
22
if (self->collapseDelay) {
23
#if MANIA_USE_PLUS
24
if (Player) {
25
foreach_active(Player, player)
26
{
27
if (Player_CheckCollisionTouch(player, self, &self->hitboxTrigger) && player->characterID == ID_MIGHTY
28
&& player->jumpAbilityState > 1) {
29
runState = true;
30
foreach_break;
31
}
32
}
33
}
34
#endif
35
36
if (!runState && --self->collapseDelay == 0)
37
runState = true;
38
}
39
else {
40
if (Player) {
41
self->direction = FLIP_NONE;
42
foreach_active(Player, player)
43
{
44
if (Player_CheckCollisionTouch(player, self, &self->hitboxTrigger)
45
#if MANIA_USE_PLUS
46
&& (!self->mightyOnly || (player->characterID == ID_MIGHTY && player->state == Player_State_MightyHammerDrop))
47
#endif
48
&& !player->sidekick && player->onGround && !player->collisionMode && !self->eventOnly && self->delay < 0xFFFF) {
49
self->stoodPos.x = player->position.x;
50
#if MANIA_USE_PLUS
51
if (player->characterID == ID_MIGHTY && player->jumpAbilityState > 1) {
52
runState = true;
53
foreach_break;
54
}
55
#endif
56
}
57
}
58
}
59
60
if (!runState && self->stoodPos.x) {
61
self->collapseDelay = self->delay;
62
if (!self->delay)
63
runState = true;
64
}
65
}
66
67
if (runState) {
68
StateMachine_Run(self->state);
69
70
RSDK.PlaySfx(CollapsingPlatform->sfxCrumble, false, 0xFF);
71
if (self->respawn) {
72
self->collapseDelay = 0;
73
self->stoodPos.x = 0;
74
}
75
else {
76
destroyEntity(self);
77
}
78
}
79
}
80
81
void CollapsingPlatform_LateUpdate(void) {}
82
83
void CollapsingPlatform_StaticUpdate(void) {}
84
85
void CollapsingPlatform_Draw(void)
86
{
87
RSDK_THIS(CollapsingPlatform);
88
Vector2 drawPos;
89
90
drawPos.x = self->position.x - (self->size.x >> 1);
91
drawPos.y = self->position.y - (self->size.y >> 1);
92
RSDK.DrawLine(drawPos.x - TO_FIXED(1), drawPos.y - TO_FIXED(1), drawPos.x + self->size.x, drawPos.y - TO_FIXED(1), 0xE0E0E0, 0x00, INK_NONE,
93
false);
94
RSDK.DrawLine(drawPos.x - TO_FIXED(1), self->size.y + drawPos.y, drawPos.x + self->size.x, self->size.y + drawPos.y, 0xE0E0E0, 0x00, INK_NONE,
95
false);
96
RSDK.DrawLine(drawPos.x - TO_FIXED(1), drawPos.y - TO_FIXED(1), drawPos.x - TO_FIXED(1), drawPos.y + self->size.y, 0xE0E0E0, 0x00, INK_NONE,
97
false);
98
RSDK.DrawLine(drawPos.x + self->size.x, drawPos.y - TO_FIXED(1), drawPos.x + self->size.x, drawPos.y + self->size.y, 0xE0E0E0, 0x00, INK_NONE,
99
false);
100
101
self->direction = FLIP_NONE;
102
RSDK.DrawSprite(&CollapsingPlatform->animator, &drawPos, false);
103
104
drawPos.x += self->size.x;
105
self->direction = FLIP_X;
106
RSDK.DrawSprite(&CollapsingPlatform->animator, &drawPos, false);
107
108
drawPos.y += self->size.y;
109
self->direction = FLIP_XY;
110
RSDK.DrawSprite(&CollapsingPlatform->animator, &drawPos, false);
111
112
drawPos.x -= self->size.x;
113
self->direction = FLIP_Y;
114
RSDK.DrawSprite(&CollapsingPlatform->animator, &drawPos, false);
115
}
116
117
void CollapsingPlatform_Create(void *data)
118
{
119
RSDK_THIS(CollapsingPlatform);
120
121
self->visible = true;
122
self->position.x &= 0xFFF80000;
123
self->position.y &= 0xFFF80000;
124
self->drawFX |= FX_FLIP;
125
self->drawGroup = Zone->objectDrawGroup[0];
126
127
if (self->targetLayer == COLLAPSEPLAT_TARGET_LOW) {
128
self->targetLayer = Zone->fgLayer[0];
129
self->drawGroup = Zone->objectDrawGroup[0];
130
}
131
else {
132
self->targetLayer = Zone->fgLayer[1];
133
self->drawGroup = Zone->objectDrawGroup[1];
134
}
135
136
if (!SceneInfo->inEditor) {
137
self->active = ACTIVE_BOUNDS;
138
self->updateRange.x = TO_FIXED(128);
139
self->updateRange.y = TO_FIXED(128);
140
int32 xOff = (self->position.x >> 20) - (self->size.x >> 21);
141
int32 yOff = (self->position.y >> 20) - (self->size.y >> 21);
142
143
if ((self->size.y & 0xFFF00000) && !(self->size.y & 0xFFF00000 & 0x80000000)) {
144
int32 sx = self->size.x >> 20;
145
int32 sy = self->size.y >> 20;
146
for (int32 y = 0; y < sy; ++y) {
147
for (int32 x = 0; x < sx; ++x) {
148
self->storedTiles[x + y * (self->size.x >> 20)] = RSDK.GetTile(self->targetLayer, x + xOff, y + yOff);
149
}
150
}
151
}
152
153
self->hitboxTrigger.left = -(self->size.x >> 17);
154
self->hitboxTrigger.top = -16 - (self->size.y >> 17);
155
self->hitboxTrigger.right = self->size.x >> 17;
156
self->hitboxTrigger.bottom = self->size.y >> 17;
157
}
158
159
switch (self->type) {
160
default:
161
case COLLAPSEPLAT_LEFT: self->state = CollapsingPlatform_State_Left; break;
162
case COLLAPSEPLAT_RIGHT: self->state = CollapsingPlatform_State_Right; break;
163
case COLLAPSEPLAT_CENTER: self->state = CollapsingPlatform_State_Center; break;
164
case COLLAPSEPLAT_LR: self->state = CollapsingPlatform_State_LeftRight; break;
165
case COLLAPSEPLAT_LRC: self->state = CollapsingPlatform_State_LeftRightCenter; break;
166
}
167
}
168
169
void CollapsingPlatform_StageLoad(void)
170
{
171
CollapsingPlatform->aniFrames = RSDK.LoadSpriteAnimation("Global/TicMark.bin", SCOPE_STAGE);
172
RSDK.SetSpriteAnimation(CollapsingPlatform->aniFrames, 0, &CollapsingPlatform->animator, true, 0);
173
174
if (RSDK.CheckSceneFolder("OOZ1") || RSDK.CheckSceneFolder("OOZ2"))
175
CollapsingPlatform->shift = 1;
176
177
if (RSDK.CheckSceneFolder("FBZ") || RSDK.CheckSceneFolder("HCZ") || RSDK.CheckSceneFolder("LRZ1") || RSDK.CheckSceneFolder("LRZ2")
178
|| RSDK.CheckSceneFolder("AIZ")) {
179
CollapsingPlatform->sfxCrumble = RSDK.GetSfx("Stage/LedgeBreak3.wav");
180
}
181
else {
182
CollapsingPlatform->sfxCrumble = RSDK.GetSfx("Stage/LedgeBreak.wav");
183
}
184
}
185
186
void CollapsingPlatform_State_Left(void)
187
{
188
RSDK_THIS(CollapsingPlatform);
189
190
uint16 *tiles = self->storedTiles;
191
int32 startTX = (self->position.x >> 20) - (self->size.x >> 21);
192
int32 startTY = (self->position.y >> 20) - (self->size.y >> 21);
193
int32 tx = self->position.x - (self->size.x >> 1) + TO_FIXED(8);
194
int32 ty = self->position.y - (self->size.y >> 1) + TO_FIXED(8);
195
196
int32 sx = self->size.x >> 20;
197
int32 sy = self->size.y >> 20;
198
199
for (int32 y = 0; y < sy; ++y) {
200
for (int32 x = 0; x < sx; ++x) {
201
EntityBreakableWall *tile = CREATE_ENTITY(BreakableWall, INT_TO_VOID(BREAKWALL_TILE_DYNAMIC), tx, ty);
202
tile->targetLayer = self->targetLayer;
203
tile->tileInfo = *tiles;
204
tile->drawGroup = self->drawGroup;
205
tile->tilePos.x = x + startTX;
206
tile->tilePos.y = y + startTY;
207
int32 timerX = x >> CollapsingPlatform->shift;
208
int32 timerY = y >> CollapsingPlatform->shift;
209
tile->timer = 3 * (sy + 2 * timerX - timerY);
210
211
++tiles;
212
tx += 0x100000;
213
}
214
215
tx -= self->size.x;
216
ty += 0x100000;
217
}
218
}
219
void CollapsingPlatform_State_Right(void)
220
{
221
RSDK_THIS(CollapsingPlatform);
222
223
uint16 *tiles = self->storedTiles;
224
int32 startTX = (self->position.x >> 20) - (self->size.x >> 21);
225
int32 startTY = (self->position.y >> 20) - (self->size.y >> 21);
226
int32 tx = self->position.x - (self->size.x >> 1) + TO_FIXED(8);
227
int32 ty = self->position.y - (self->size.y >> 1) + TO_FIXED(8);
228
229
int32 timerSX = self->size.x >> CollapsingPlatform->shift >> 20;
230
231
int32 sx = self->size.x >> 20;
232
int32 sy = self->size.y >> 20;
233
234
for (int32 y = 0; y < sy; ++y) {
235
for (int32 x = 0; x < sx; ++x) {
236
EntityBreakableWall *tile = CREATE_ENTITY(BreakableWall, INT_TO_VOID(BREAKWALL_TILE_DYNAMIC), tx, ty);
237
tile->targetLayer = self->targetLayer;
238
tile->tileInfo = *tiles;
239
tile->drawGroup = self->drawGroup;
240
tile->tilePos.x = x + startTX;
241
tile->tilePos.y = y + startTY;
242
int32 timerX = x >> CollapsingPlatform->shift;
243
int32 timerY = y >> CollapsingPlatform->shift;
244
tile->timer = 3 * (sy + 2 * (timerSX - timerX) - timerY);
245
246
++tiles;
247
tx += 0x100000;
248
}
249
250
tx -= self->size.x;
251
ty += 0x100000;
252
}
253
}
254
void CollapsingPlatform_State_Center(void)
255
{
256
RSDK_THIS(CollapsingPlatform);
257
258
uint16 *tiles = self->storedTiles;
259
int32 startTX = (self->position.x >> 20) - (self->size.x >> 21);
260
int32 startTY = (self->position.y >> 20) - (self->size.y >> 21);
261
int32 tx = self->position.x - (self->size.x >> 1) + TO_FIXED(8);
262
int32 ty = self->position.y - (self->size.y >> 1) + TO_FIXED(8);
263
264
int32 timerSX = self->size.x >> CollapsingPlatform->shift >> 20;
265
int32 timerSY = self->size.y >> CollapsingPlatform->shift >> 20;
266
267
int32 sx = self->size.x >> 20;
268
int32 sy = self->size.y >> 20;
269
270
for (int32 y = 0; y < sy; ++y) {
271
for (int32 x = 0; x < sx; ++x) {
272
EntityBreakableWall *tile = CREATE_ENTITY(BreakableWall, INT_TO_VOID(BREAKWALL_TILE_DYNAMIC), tx, ty);
273
tile->targetLayer = self->targetLayer;
274
tile->tileInfo = *tiles;
275
tile->drawGroup = self->drawGroup;
276
tile->tilePos.x = x + startTX;
277
tile->tilePos.y = y + startTY;
278
int32 timerX = abs((timerSX >> 1) - (x >> CollapsingPlatform->shift));
279
int32 timerY = y >> CollapsingPlatform->shift;
280
tile->timer = 3 * (timerSY + 2 * timerX - timerY);
281
282
if (!(timerSX & 1) && x >> CollapsingPlatform->shift < (timerSX >> 1))
283
tile->timer -= 6;
284
285
++tiles;
286
tx += 0x100000;
287
}
288
289
tx -= self->size.x;
290
ty += 0x100000;
291
}
292
}
293
void CollapsingPlatform_State_LeftRight(void)
294
{
295
RSDK_THIS(CollapsingPlatform);
296
297
int32 px = self->stoodPos.x;
298
int32 x = self->position.x;
299
300
if (px < x)
301
CollapsingPlatform_State_Left();
302
else
303
CollapsingPlatform_State_Right();
304
}
305
void CollapsingPlatform_State_LeftRightCenter(void)
306
{
307
RSDK_THIS(CollapsingPlatform);
308
309
int32 px = self->stoodPos.x;
310
int32 x = self->position.x;
311
312
if (abs(px - x) < self->size.x / 6)
313
CollapsingPlatform_State_Center();
314
else if (px < x)
315
CollapsingPlatform_State_Left();
316
else
317
CollapsingPlatform_State_Right();
318
}
319
320
#if GAME_INCLUDE_EDITOR
321
void CollapsingPlatform_EditorDraw(void)
322
{
323
RSDK_THIS(CollapsingPlatform);
324
325
DrawHelpers_DrawRectOutline(self->position.x, self->position.y, self->size.x, self->size.y, 0xFFFF00);
326
327
Vector2 drawPos;
328
drawPos.x = self->position.x - (self->size.x >> 1);
329
drawPos.y = self->position.y - (self->size.y >> 1);
330
331
self->direction = FLIP_NONE;
332
RSDK.DrawSprite(&CollapsingPlatform->animator, &drawPos, false);
333
334
drawPos.x += self->size.x;
335
self->direction = FLIP_X;
336
RSDK.DrawSprite(&CollapsingPlatform->animator, &drawPos, false);
337
338
drawPos.y += self->size.y;
339
self->direction = FLIP_XY;
340
RSDK.DrawSprite(&CollapsingPlatform->animator, &drawPos, false);
341
342
drawPos.x -= self->size.x;
343
self->direction = FLIP_Y;
344
RSDK.DrawSprite(&CollapsingPlatform->animator, &drawPos, false);
345
}
346
347
void CollapsingPlatform_EditorLoad(void)
348
{
349
CollapsingPlatform->aniFrames = RSDK.LoadSpriteAnimation("Global/TicMark.bin", SCOPE_STAGE);
350
RSDK.SetSpriteAnimation(CollapsingPlatform->aniFrames, 0, &CollapsingPlatform->animator, true, 0);
351
352
RSDK_ACTIVE_VAR(CollapsingPlatform, type);
353
RSDK_ENUM_VAR("Left", COLLAPSEPLAT_LEFT);
354
RSDK_ENUM_VAR("Right", COLLAPSEPLAT_RIGHT);
355
RSDK_ENUM_VAR("Center", COLLAPSEPLAT_CENTER);
356
RSDK_ENUM_VAR("Left or Right", COLLAPSEPLAT_LR);
357
RSDK_ENUM_VAR("Base on Player Position", COLLAPSEPLAT_LRC);
358
359
RSDK_ACTIVE_VAR(CollapsingPlatform, targetLayer);
360
RSDK_ENUM_VAR("Low", COLLAPSEPLAT_TARGET_LOW);
361
RSDK_ENUM_VAR("High", COLLAPSEPLAT_TARGET_HIGH);
362
}
363
#endif
364
365
void CollapsingPlatform_Serialize(void)
366
{
367
RSDK_EDITABLE_VAR(CollapsingPlatform, VAR_VECTOR2, size);
368
RSDK_EDITABLE_VAR(CollapsingPlatform, VAR_BOOL, respawn);
369
RSDK_EDITABLE_VAR(CollapsingPlatform, VAR_UINT16, targetLayer);
370
RSDK_EDITABLE_VAR(CollapsingPlatform, VAR_UINT8, type);
371
RSDK_EDITABLE_VAR(CollapsingPlatform, VAR_ENUM, delay);
372
RSDK_EDITABLE_VAR(CollapsingPlatform, VAR_BOOL, eventOnly);
373
RSDK_EDITABLE_VAR(CollapsingPlatform, VAR_BOOL, mightyOnly);
374
}
375
376