Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/LRZ/LRZConveyor.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: LRZConveyor Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectLRZConveyor *LRZConveyor;
11
12
void LRZConveyor_Update(void)
13
{
14
RSDK_THIS(LRZConveyor);
15
16
if (self->globalControl) {
17
self->off = LRZ2Setup->conveyorOff;
18
self->direction = self->startDir ^ LRZ2Setup->conveyorDir;
19
}
20
else {
21
LRZConveyor_HandleBehaviour();
22
}
23
24
LRZConveyor_HandlePlayerInteractions();
25
26
if (!self->off) {
27
RSDK.ProcessAnimation(&self->wheelAnimator);
28
RSDK.ProcessAnimation(&self->smallWheelAnimator);
29
}
30
}
31
32
void LRZConveyor_LateUpdate(void) {}
33
34
void LRZConveyor_StaticUpdate(void) {}
35
36
void LRZConveyor_Draw(void)
37
{
38
LRZConveyor_DrawConveyorLines();
39
LRZConveyor_DrawWheels();
40
}
41
42
void LRZConveyor_Create(void *data)
43
{
44
RSDK_THIS(LRZConveyor);
45
46
self->active = ACTIVE_BOUNDS;
47
self->drawGroup = Zone->objectDrawGroup[0];
48
self->startPos = self->position;
49
self->updateRange.x = (self->length + 0x80) << 16;
50
self->updateRange.y = (self->length * (self->slope << 8)) + 0x800000;
51
self->visible = true;
52
self->drawFX = FX_FLIP;
53
self->isOff = self->off;
54
self->startDir = self->direction;
55
56
if (SceneInfo->inEditor) {
57
if (!self->speed)
58
self->speed = 8;
59
}
60
else {
61
self->speed = abs(self->speed);
62
self->taggedButton = LRZ2Setup_SetupTagLink(self->buttonTag, (Entity *)self);
63
}
64
65
self->hitbox.left = -8;
66
self->hitbox.top = -8;
67
self->hitbox.right = 8;
68
self->hitbox.bottom = 8;
69
70
RSDK.SetSpriteAnimation(LRZConveyor->aniFrames, 0, &self->wheelAnimator, true, 0);
71
RSDK.SetSpriteAnimation(LRZConveyor->aniFrames, 1, &self->smallWheelAnimator, true, 0);
72
}
73
74
void LRZConveyor_StageLoad(void)
75
{
76
LRZConveyor->aniFrames = RSDK.LoadSpriteAnimation("LRZ2/LRZConveyor.bin", SCOPE_STAGE);
77
78
color lineColors[] = { 0x225BDD, 0x429AFD, 0x51DEFF, 0xAFFDF0 };
79
for (int32 i = 0; i < 0x40; ++i) LRZConveyor->lineColors[i] = lineColors[i & 3];
80
}
81
82
void LRZConveyor_HandleBehaviour(void)
83
{
84
RSDK_THIS(LRZConveyor);
85
86
if (self->buttonTag && self->taggedButton) {
87
switch (self->buttonBehavior) {
88
case LRZCONVEYOR_BEHAVIOR_CHANGEACTIVE:
89
if (self->taggedButton->activated)
90
self->off = self->isOff == 0;
91
break;
92
93
case LRZCONVEYOR_BEHAVIOR_CHANGEACTIVE_TOGGLE: self->off = self->taggedButton->toggled ^ self->isOff; break;
94
95
case LRZCONVEYOR_BEHAVIOR_CHANGEDIR:
96
if (self->taggedButton->activated)
97
self->direction = self->startDir == FLIP_NONE;
98
break;
99
100
case LRZCONVEYOR_BEHAVIOR_CHANGEDIR_TOGGLE: self->direction = self->startDir ^ self->taggedButton->toggled; break;
101
102
default: break;
103
}
104
}
105
}
106
107
void LRZConveyor_HandlePlayerInteractions(void)
108
{
109
RSDK_THIS(LRZConveyor);
110
111
int32 velX = (self->speed << 14) * (2 * (self->direction == FLIP_X) - 1);
112
113
foreach_active(Player, player)
114
{
115
int32 side = LRZConveyor_HandlePlayerCollisions(self, player, NULL);
116
if (side == C_TOP && !self->off) {
117
if (player->onGround)
118
player->position.y += 0x10000;
119
else
120
player->velocity.x = velX;
121
122
player->position.x += velX;
123
}
124
else if ((side == C_LEFT || side == C_RIGHT) && !self->off && !player->onGround) {
125
player->velocity.x = velX;
126
}
127
}
128
}
129
130
int32 LRZConveyor_HandlePlayerCollisions(EntityLRZConveyor *conveyor, void *p, Hitbox *hitboxPtr)
131
{
132
EntityPlayer *player = (EntityPlayer *)p;
133
134
Hitbox hitbox;
135
memset(&hitbox, 0, sizeof(hitbox));
136
137
int32 distX = player->position.x - conveyor->position.x;
138
139
hitbox.right = (conveyor->length + 32) >> 1;
140
hitbox.left = -(conveyor->length + 32) >> 1;
141
142
if (abs(distX) >> 16 > conveyor->length >> 1) {
143
if (abs(distX) >> 16 <= (conveyor->length >> 1) + 16) {
144
int32 len = conveyor->length >> 1;
145
if (distX >= 0) {
146
if (distX >> 16 < len)
147
len = distX >> 16;
148
}
149
else {
150
len = -(conveyor->length >> 1);
151
if (distX >> 16 > len)
152
len = distX >> 16;
153
}
154
155
int32 slope = (len * (conveyor->slope << 8)) >> 16;
156
int32 angle = RSDK.ATan2(distX - (conveyor->length << 15) * (((distX >> 31) & 0xFFFFFFFE) + 1), 0x100000);
157
hitbox.top = slope - (RSDK.Sin256(angle) >> 4);
158
hitbox.bottom = slope + (RSDK.Sin256(angle) >> 4);
159
}
160
}
161
else {
162
int32 slope = ((distX >> 16) * (conveyor->slope << 8)) >> 16;
163
hitbox.top = slope - 16;
164
hitbox.bottom = slope + 16;
165
}
166
167
int32 storeDir = conveyor->direction;
168
conveyor->direction = FLIP_NONE;
169
170
int32 side = C_NONE;
171
if (Player_CheckValidState(player)) {
172
side = Player_CheckCollisionBox(player, conveyor, &hitbox);
173
conveyor->direction = storeDir;
174
}
175
else {
176
Hitbox playerHitbox;
177
if (hitboxPtr) {
178
playerHitbox = *hitboxPtr;
179
}
180
else {
181
playerHitbox.left = -8;
182
playerHitbox.top = -8;
183
playerHitbox.right = 8;
184
playerHitbox.bottom = 8;
185
}
186
187
side = MathHelpers_CheckBoxCollision(conveyor, &hitbox, player, &playerHitbox);
188
conveyor->direction = storeDir;
189
}
190
191
return side;
192
}
193
194
void LRZConveyor_DrawWheels(void)
195
{
196
RSDK_THIS(LRZConveyor);
197
198
Vector2 drawPos = self->position;
199
drawPos.x -= self->length << 15;
200
drawPos.y -= (self->slope << 8) * (self->length >> 1);
201
RSDK.DrawSprite(&self->wheelAnimator, &drawPos, false);
202
203
int32 len = self->length << 16;
204
if (len > 0x300000) {
205
int32 size = (len - 0x300001) / 0x300000 + 1;
206
207
if ((len - 0x300001) / 0x300000 != -1) {
208
int32 incX = len / size;
209
210
for (int32 i = 0; i < size; ++i) {
211
drawPos.x += incX;
212
drawPos.y += (incX >> 8) * self->slope;
213
RSDK.DrawSprite(&self->smallWheelAnimator, &drawPos, false);
214
}
215
}
216
}
217
218
drawPos = self->position;
219
drawPos.x += self->length << 15;
220
drawPos.y += (self->slope << 8) * (self->length >> 1);
221
RSDK.DrawSprite(&self->wheelAnimator, &drawPos, false);
222
}
223
224
void LRZConveyor_DrawDeformedLine(int32 startX, int32 startY, int32 endX, int32 endY, int32 offsetX, int32 offsetY, int32 len, color *color)
225
{
226
RSDK_THIS(LRZConveyor);
227
228
int32 count = (self->length >> 1) + ((self->length & 1) != 0);
229
230
int32 currentX = startX;
231
int32 currentY = startY;
232
for (int32 i = 0; i < count; ++i) {
233
int32 colorID = 0;
234
if (self->direction == FLIP_X)
235
colorID = count - len % count - 1;
236
else
237
colorID = len % count;
238
239
if (!self->off)
240
colorID += Zone->timer >> 1;
241
242
int32 prevX = currentX;
243
int32 prevY = currentY;
244
currentX += (endX - startX) / count;
245
currentY += (endY - startY) / count;
246
247
uint32 lineColor = color ? *color : LRZConveyor->lineColors[(colorID % count) & 0x3F];
248
RSDK.DrawLine(prevX + offsetX, prevY + offsetY, currentX + offsetX, currentY + offsetY, lineColor, 0x7F, INK_NONE, false);
249
250
++len;
251
}
252
}
253
254
void LRZConveyor_DrawConveyorLines(void)
255
{
256
RSDK_THIS(LRZConveyor);
257
258
color color = 0x51DEFF;
259
260
int32 slopeLen = (self->length >> 1) * (self->slope << 8);
261
int32 startX = self->position.x - (self->length << 15);
262
int32 startY = slopeLen + self->position.y + 0xF0000;
263
int32 endX = self->position.x + (self->length << 15);
264
int32 endY = slopeLen + self->position.y - 0x100000;
265
int32 slopeY = self->position.y - slopeLen;
266
267
int32 len = (self->length >> 1) + ((self->length & 1) != 0);
268
LRZConveyor_DrawDeformedLine(startX, slopeY - 0x100000, endX, endY, 0, 0, 0, NULL);
269
LRZConveyor_DrawDeformedLine(endX, startY, startX, slopeY + 0xF0000, 0, 0, len, NULL);
270
LRZConveyor_DrawDeformedLine(startX, slopeY - 0x100000, endX, endY, 0, 0x10000, 0, NULL);
271
LRZConveyor_DrawDeformedLine(endX, startY, startX, slopeY + 0xF0000, 0, -0x10000, len, NULL);
272
LRZConveyor_DrawDeformedLine(startX, slopeY - 0x100000, endX, endY, 0, 0x20000, 0, &color);
273
LRZConveyor_DrawDeformedLine(endX, startY, startX, slopeY + 0xF0000, 0, -0x20000, len, &color);
274
}
275
276
#if GAME_INCLUDE_EDITOR
277
void LRZConveyor_EditorDraw(void)
278
{
279
RSDK_THIS(LRZConveyor);
280
281
self->startPos = self->position;
282
self->updateRange.x = (self->length + 0x80) << 16;
283
self->updateRange.y = (self->length * (self->slope << 8)) + 0x800000;
284
self->startDir = self->direction;
285
286
int32 speed = self->speed;
287
self->speed = abs(self->speed);
288
self->speed = speed;
289
290
LRZConveyor_Draw();
291
292
if (showGizmos()) {
293
self->taggedButton = LRZ2Setup_SetupTagLink(self->buttonTag, (Entity *)self);
294
295
RSDK_DRAWING_OVERLAY(true);
296
if (self->taggedButton) {
297
DrawHelpers_DrawArrow(self->taggedButton->position.x, self->taggedButton->position.y, self->position.x, self->position.y, 0xFFFF00,
298
INK_NONE, 0xFF);
299
}
300
RSDK_DRAWING_OVERLAY(false);
301
}
302
}
303
304
void LRZConveyor_EditorLoad(void)
305
{
306
LRZConveyor_StageLoad();
307
308
RSDK_ACTIVE_VAR(LRZConveyor, direction);
309
RSDK_ENUM_VAR("Right", FLIP_NONE);
310
RSDK_ENUM_VAR("Left", FLIP_X);
311
312
RSDK_ACTIVE_VAR(LRZConveyor, buttonBehavior);
313
RSDK_ENUM_VAR("Change Activated", LRZCONVEYOR_BEHAVIOR_CHANGEACTIVE);
314
RSDK_ENUM_VAR("Change Activated (Togglable)", LRZCONVEYOR_BEHAVIOR_CHANGEACTIVE_TOGGLE);
315
RSDK_ENUM_VAR("Change Direction", LRZCONVEYOR_BEHAVIOR_CHANGEDIR);
316
RSDK_ENUM_VAR("Change Direction (Togglable)", LRZCONVEYOR_BEHAVIOR_CHANGEDIR_TOGGLE);
317
}
318
#endif
319
320
void LRZConveyor_Serialize(void)
321
{
322
RSDK_EDITABLE_VAR(LRZConveyor, VAR_UINT8, direction);
323
RSDK_EDITABLE_VAR(LRZConveyor, VAR_ENUM, slope);
324
RSDK_EDITABLE_VAR(LRZConveyor, VAR_UINT32, length);
325
RSDK_EDITABLE_VAR(LRZConveyor, VAR_ENUM, speed);
326
RSDK_EDITABLE_VAR(LRZConveyor, VAR_BOOL, globalControl);
327
RSDK_EDITABLE_VAR(LRZConveyor, VAR_ENUM, buttonTag);
328
RSDK_EDITABLE_VAR(LRZConveyor, VAR_UINT8, buttonBehavior);
329
RSDK_EDITABLE_VAR(LRZConveyor, VAR_BOOL, off);
330
}
331
332