Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/PGZ/PSZDoor.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: PSZDoor Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectPSZDoor *PSZDoor;
11
12
void PSZDoor_Update(void)
13
{
14
RSDK_THIS(PSZDoor);
15
16
int32 offsetX = 0;
17
int32 offsetY = 0;
18
19
int32 speed = 0;
20
switch (self->open ^ self->orientation) {
21
case PSZDOOR_ORIENATION_D:
22
offsetY = -0x10000;
23
speed = -self->speed;
24
break;
25
26
case PSZDOOR_ORIENATION_U:
27
speed = self->speed;
28
offsetY = 0x10000;
29
break;
30
31
case PSZDOOR_ORIENATION_L:
32
speed = self->speed;
33
offsetX = -0x10000;
34
break;
35
36
case PSZDOOR_ORIENATION_R:
37
offsetX = 0x10000;
38
speed = -self->speed;
39
break;
40
41
default: break;
42
}
43
44
int32 startX = self->doorPos.x;
45
int32 startY = self->doorPos.y;
46
47
if (self->shouldMove) {
48
if (PSZDoor_GetRemainingDistance() > 0) {
49
self->doorPos.x += self->speed * (offsetX >> 3);
50
self->doorPos.y += self->speed * (offsetY >> 3);
51
self->rotation += speed;
52
}
53
54
if (PSZDoor_GetRemainingDistance() < 0) {
55
self->doorPos.x = self->targetPos.x;
56
self->doorPos.y = self->targetPos.y;
57
}
58
59
if (self->doorPos.x == self->targetPos.x && self->doorPos.y == self->targetPos.y) {
60
self->shouldMove = false;
61
self->open ^= 1;
62
}
63
}
64
65
int32 posX = self->doorPos.x - startX;
66
int32 posY = self->doorPos.y - startY;
67
68
bool32 autoOpen = false;
69
foreach_active(Player, player)
70
{
71
// this was a weird one where apparently it used doorPos directly which is very much undefined behavior lol
72
// so much so that it breaks as of v5U :]
73
Vector2 storePos = self->position;
74
self->position = self->doorPos;
75
if (Player_CheckCollisionBox(player, self, &PSZDoor->hitboxes[self->doorAnimator.frameID]) == C_TOP) {
76
if (self->orientation >= PSZDOOR_ORIENATION_L)
77
player->position.x += posX;
78
else
79
player->position.y += posY;
80
}
81
self->position = storePos;
82
83
switch (self->automatic) {
84
default:
85
case PSZDOOR_AUTO_NONE: break;
86
87
case PSZDOOR_AUTO_LEFT:
88
if (self->orientation >= PSZDOOR_ORIENATION_L) {
89
if (player->position.y < self->position.y && abs(player->position.x - self->position.x) < 0x200000)
90
autoOpen = true;
91
}
92
else {
93
if (player->position.x < self->position.x && abs(player->position.y - self->position.y) < 0x200000)
94
autoOpen = true;
95
}
96
break;
97
98
case PSZDOOR_AUTO_RIGHT:
99
if (self->orientation >= PSZDOOR_ORIENATION_L) {
100
if (player->position.y > self->position.y && abs(player->position.x - self->position.x) < 0x200000)
101
autoOpen = true;
102
}
103
else {
104
if (player->position.x > self->position.x && abs(player->position.y - self->position.y) < 0x200000)
105
autoOpen = true;
106
}
107
break;
108
}
109
}
110
111
EntityDoorTrigger *trigger = self->trigger;
112
if (trigger && ((trigger->classID == DoorTrigger->classID && trigger->bulbAnimator.frameID == 1) || autoOpen)) {
113
if (self->onScreen)
114
RSDK.PlaySfx(PSZDoor->sfxOpen, false, 255);
115
116
self->startPos = self->doorPos;
117
self->trigger = 0;
118
self->shouldMove = true;
119
self->targetPos.x = self->doorPos.x + 112 * offsetX;
120
self->targetPos.y = self->doorPos.y + 112 * offsetY;
121
}
122
}
123
124
void PSZDoor_LateUpdate(void) {}
125
126
void PSZDoor_StaticUpdate(void) {}
127
128
void PSZDoor_Draw(void)
129
{
130
RSDK_THIS(PSZDoor);
131
132
Vector2 drawPos;
133
RSDK.DrawSprite(&self->doorAnimator, &self->doorPos, false);
134
135
self->doorAnimator.frameID = 2;
136
drawPos.x = self->position.x + self->offset.x;
137
drawPos.y = self->position.y + self->offset.y;
138
RSDK.DrawSprite(&self->cogAnimator, &drawPos, false);
139
RSDK.DrawSprite(&self->doorAnimator, &drawPos, false);
140
141
if (self->orientation < PSZDOOR_ORIENATION_L)
142
drawPos.x -= 2 * self->offset.x;
143
else
144
drawPos.y -= 2 * self->offset.y;
145
146
int32 rotation = self->rotation;
147
self->rotation = 0x100 - rotation;
148
RSDK.DrawSprite(&self->cogAnimator, &drawPos, false);
149
RSDK.DrawSprite(&self->doorAnimator, &drawPos, false);
150
151
self->rotation = rotation;
152
self->doorAnimator.frameID = self->orientation >= PSZDOOR_ORIENATION_L;
153
}
154
155
void PSZDoor_Create(void *data)
156
{
157
RSDK_THIS(PSZDoor);
158
159
if (!self->speed)
160
self->speed = 8;
161
162
if (!SceneInfo->inEditor) {
163
self->active = ACTIVE_BOUNDS;
164
self->visible = true;
165
self->drawGroup = Zone->objectDrawGroup[0];
166
self->updateRange.y = 0x800000;
167
self->updateRange.x = 0x800000;
168
RSDK.SetSpriteAnimation(PSZDoor->aniFrames, 0, &self->doorAnimator, true, 0);
169
RSDK.SetSpriteAnimation(PSZDoor->aniFrames, 1, &self->cogAnimator, true, 0);
170
171
self->doorPos = self->position;
172
self->drawFX = FX_ROTATE;
173
self->direction = self->orientation & 1;
174
if (self->orientation < PSZDOOR_ORIENATION_L)
175
self->direction = 2 * (self->orientation & 1);
176
else
177
self->doorAnimator.frameID = 1;
178
179
switch (self->orientation) {
180
case PSZDOOR_ORIENATION_D:
181
self->offset.y = -0x380000;
182
self->offset.x = -0x130000;
183
184
if (self->open)
185
self->doorPos.y -= 0x700000;
186
break;
187
188
case PSZDOOR_ORIENATION_U:
189
self->offset.y = 0x380000;
190
self->offset.x = -0x130000;
191
192
if (self->open)
193
self->doorPos.y += 0x700000;
194
break;
195
196
case PSZDOOR_ORIENATION_L:
197
self->offset.x = -0x380000;
198
self->offset.y = -0x130000;
199
200
if (self->open)
201
self->doorPos.x -= 0x700000;
202
break;
203
204
case PSZDOOR_ORIENATION_R:
205
self->offset.x = 0x380000;
206
self->offset.y = -0x130000;
207
208
if (self->open)
209
self->doorPos.x += 0x700000;
210
break;
211
212
default: break;
213
}
214
215
foreach_all(DoorTrigger, trigger)
216
{
217
if (trigger->id == self->id) {
218
self->updateRange.x += abs(self->position.x - trigger->position.x);
219
self->updateRange.y += abs(self->position.y - trigger->position.y);
220
self->trigger = trigger;
221
}
222
}
223
}
224
}
225
226
void PSZDoor_StageLoad(void)
227
{
228
if (RSDK.CheckSceneFolder("PSZ1"))
229
PSZDoor->aniFrames = RSDK.LoadSpriteAnimation("PSZ1/PSZDoor.bin", SCOPE_STAGE);
230
231
PSZDoor->hitboxes[0].top = -56;
232
PSZDoor->hitboxes[0].left = -12;
233
PSZDoor->hitboxes[0].bottom = 56;
234
PSZDoor->hitboxes[0].right = 12;
235
236
PSZDoor->hitboxes[1].top = -12;
237
PSZDoor->hitboxes[1].left = -56;
238
PSZDoor->hitboxes[1].bottom = 12;
239
PSZDoor->hitboxes[1].right = 56;
240
241
PSZDoor->sfxOpen = RSDK.GetSfx("Stage/Open.wav");
242
}
243
244
int32 PSZDoor_GetRemainingDistance(void)
245
{
246
RSDK_THIS(PSZDoor);
247
248
if (self->shouldMove) {
249
switch (self->open ^ self->orientation) {
250
case PSZDOOR_ORIENATION_D: return self->doorPos.y - self->targetPos.y; break;
251
case PSZDOOR_ORIENATION_U: return self->targetPos.y - self->doorPos.y; break;
252
case PSZDOOR_ORIENATION_L: return self->doorPos.x - self->targetPos.x; break;
253
case PSZDOOR_ORIENATION_R: return self->targetPos.x - self->doorPos.x; break;
254
255
default: break;
256
}
257
}
258
259
return 0;
260
}
261
262
#if GAME_INCLUDE_EDITOR
263
void PSZDoor_EditorDraw(void)
264
{
265
RSDK_THIS(PSZDoor);
266
267
self->updateRange.y = 0x800000;
268
self->updateRange.x = 0x800000;
269
RSDK.SetSpriteAnimation(PSZDoor->aniFrames, 0, &self->doorAnimator, true, 0);
270
RSDK.SetSpriteAnimation(PSZDoor->aniFrames, 1, &self->cogAnimator, true, 0);
271
272
self->doorPos = self->position;
273
self->drawFX = FX_ROTATE;
274
self->direction = self->orientation & 1;
275
276
if (self->orientation < PSZDOOR_ORIENATION_L)
277
self->direction = 2 * (self->orientation & 1);
278
else
279
self->doorAnimator.frameID = 1;
280
281
switch (self->orientation) {
282
case PSZDOOR_ORIENATION_D:
283
self->offset.y = -0x380000;
284
self->offset.x = -0x130000;
285
if (self->open)
286
self->doorPos.y -= 0x700000;
287
break;
288
289
case PSZDOOR_ORIENATION_U:
290
self->offset.y = 0x380000;
291
self->offset.x = -0x130000;
292
if (self->open)
293
self->doorPos.y += 0x700000;
294
break;
295
296
case PSZDOOR_ORIENATION_L:
297
self->offset.x = -0x380000;
298
self->offset.y = -0x130000;
299
if (self->open)
300
self->doorPos.x -= 0x700000;
301
break;
302
303
case PSZDOOR_ORIENATION_R:
304
self->offset.x = 0x380000;
305
self->offset.y = -0x130000;
306
if (self->open)
307
self->doorPos.x += 0x700000;
308
break;
309
310
default: break;
311
}
312
313
PSZDoor_Draw();
314
315
if (showGizmos()) {
316
self->doorPos = self->position;
317
self->inkEffect = INK_BLEND;
318
self->open ^= 1;
319
320
switch (self->orientation) {
321
case PSZDOOR_ORIENATION_D:
322
self->offset.y = -0x380000;
323
self->offset.x = -0x130000;
324
if (self->open)
325
self->doorPos.y -= 0x700000;
326
break;
327
328
case PSZDOOR_ORIENATION_U:
329
self->offset.y = 0x380000;
330
self->offset.x = -0x130000;
331
if (self->open)
332
self->doorPos.y += 0x700000;
333
break;
334
335
case PSZDOOR_ORIENATION_L:
336
self->offset.x = -0x380000;
337
self->offset.y = -0x130000;
338
if (self->open)
339
self->doorPos.x -= 0x700000;
340
break;
341
342
case PSZDOOR_ORIENATION_R:
343
self->offset.x = 0x380000;
344
self->offset.y = -0x130000;
345
if (self->open)
346
self->doorPos.x += 0x700000;
347
break;
348
349
default: break;
350
}
351
352
PSZDoor_Draw();
353
354
self->open ^= 1;
355
self->inkEffect = INK_NONE;
356
357
self->trigger = NULL;
358
foreach_all(DoorTrigger, trigger)
359
{
360
if (trigger->id == self->id)
361
self->trigger = trigger;
362
}
363
364
if (self->trigger) {
365
DrawHelpers_DrawArrow(self->trigger->position.x, self->trigger->position.y, self->position.x, self->position.y, 0xFFFF00, INK_NONE, 0xFF);
366
}
367
}
368
}
369
370
void PSZDoor_EditorLoad(void)
371
{
372
PSZDoor->aniFrames = RSDK.LoadSpriteAnimation("PSZ1/PSZDoor.bin", SCOPE_STAGE);
373
374
RSDK_ACTIVE_VAR(PSZDoor, orientation);
375
RSDK_ENUM_VAR("Down", PSZDOOR_ORIENATION_D);
376
RSDK_ENUM_VAR("Up", PSZDOOR_ORIENATION_U);
377
RSDK_ENUM_VAR("Left", PSZDOOR_ORIENATION_L);
378
RSDK_ENUM_VAR("Right", PSZDOOR_ORIENATION_R);
379
380
RSDK_ACTIVE_VAR(PSZDoor, automatic);
381
RSDK_ENUM_VAR("Not Automatic", PSZDOOR_AUTO_NONE);
382
RSDK_ENUM_VAR("Auto-Open when player is to the left", PSZDOOR_AUTO_LEFT);
383
RSDK_ENUM_VAR("Auto-Open when player is to the right", PSZDOOR_AUTO_RIGHT);
384
}
385
#endif
386
387
void PSZDoor_Serialize(void)
388
{
389
RSDK_EDITABLE_VAR(PSZDoor, VAR_UINT8, orientation);
390
RSDK_EDITABLE_VAR(PSZDoor, VAR_BOOL, open);
391
RSDK_EDITABLE_VAR(PSZDoor, VAR_ENUM, speed);
392
RSDK_EDITABLE_VAR(PSZDoor, VAR_UINT8, id);
393
RSDK_EDITABLE_VAR(PSZDoor, VAR_ENUM, automatic);
394
}
395
396