Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/Pinball/PBL_Flipper.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: PBL_Flipper Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
#if MANIA_USE_PLUS
11
ObjectPBL_Flipper *PBL_Flipper;
12
13
void PBL_Flipper_Update(void)
14
{
15
RSDK_THIS(PBL_Flipper);
16
17
if (self->direction) {
18
self->buttonPress = TriggerInfoL[CONT_P1].keyBumper.press || ControllerInfo[CONT_P1].keyA.press || ControllerInfo[CONT_P1].keyX.press
19
|| ControllerInfo[CONT_P1].keyC.press;
20
21
self->buttonDown = TriggerInfoL[CONT_P1].keyBumper.down || ControllerInfo[CONT_P1].keyA.down || ControllerInfo[CONT_P1].keyX.down
22
|| ControllerInfo[CONT_P1].keyC.down;
23
}
24
else {
25
self->buttonPress = TriggerInfoR[CONT_P1].keyBumper.press || ControllerInfo[CONT_P1].keyA.press || ControllerInfo[CONT_P1].keyB.press
26
|| ControllerInfo[CONT_P1].keyC.press;
27
28
self->buttonDown = TriggerInfoR[CONT_P1].keyBumper.down || ControllerInfo[CONT_P1].keyA.down || ControllerInfo[CONT_P1].keyB.down
29
|| ControllerInfo[CONT_P1].keyC.down;
30
}
31
32
StateMachine_Run(self->state);
33
34
if (self->retractable) {
35
foreach_active(PBL_Player, player)
36
{
37
if (player->position.y >= self->position.y - 0x100000 || self->minCraneID > PBL_Setup->sectorID) {
38
if (player->position.y > self->position.y + 0x100000)
39
self->flipperActive = false;
40
}
41
else {
42
self->flipperActive = true;
43
}
44
}
45
46
if (self->flipperActive) {
47
if (self->scale.y < 0x100)
48
self->scale.y += 0x10;
49
}
50
else if (self->scale.y > 0) {
51
self->scale.y -= 0x10;
52
}
53
}
54
}
55
56
void PBL_Flipper_LateUpdate(void)
57
{
58
RSDK_THIS(PBL_Flipper);
59
60
int32 z = self->position.y;
61
int32 y = self->height;
62
int32 x = self->position.x;
63
64
Matrix *m = &PBL_Camera->matWorld;
65
self->zdepth = m->values[2][1] * (y >> 16) + m->values[2][2] * (z >> 16) + m->values[2][0] * (x >> 16) + m->values[2][3];
66
67
if (self->zdepth >= 0x4000) {
68
int32 depth = ((m->values[0][3] << 8) + ((m->values[0][2] * (z >> 8)) & 0xFFFFFF00) + ((m->values[0][0] * (x >> 8)) & 0xFFFFFF00)
69
+ ((m->values[0][1] * (self->height >> 8)) & 0xFFFFFF00));
70
depth /= self->zdepth;
71
self->visible = abs(depth) < 0x100;
72
}
73
}
74
75
void PBL_Flipper_StaticUpdate(void) {}
76
77
void PBL_Flipper_Draw(void)
78
{
79
RSDK_THIS(PBL_Flipper);
80
81
if (self->zdepth >= 0x4000 && self->minCraneID <= PBL_Setup->sectorID) {
82
RSDK.Prepare3DScene(PBL_Flipper->sceneIndex);
83
84
RSDK.MatrixScaleXYZ(&self->matTransform, self->scale.x, self->scale.y, 0x100);
85
RSDK.MatrixTranslateXYZ(&self->matTransform, self->position.x, self->height, self->position.y, false);
86
RSDK.MatrixRotateY(&self->matNormal, self->angle >> 8);
87
88
RSDK.MatrixMultiply(&self->matWorld, &self->matNormal, &self->matTransform);
89
RSDK.MatrixMultiply(&self->matWorld, &self->matWorld, &PBL_Camera->matWorld);
90
91
if (PBL_Camera->useAltMatNormal)
92
RSDK.MatrixMultiply(&self->matNormal, &self->matNormal, &PBL_Camera->matNormal);
93
else
94
RSDK.MatrixMultiply(&self->matNormal, &self->matNormal, &PBL_Camera->matNormalItem);
95
96
RSDK.AddModelTo3DScene(PBL_Flipper->modelFrames, PBL_Flipper->sceneIndex, PBL_Flipper->drawType, &self->matWorld, &self->matNormal, 0xFFFFFF);
97
98
RSDK.Draw3DScene(PBL_Flipper->sceneIndex);
99
}
100
}
101
102
void PBL_Flipper_Create(void *data)
103
{
104
RSDK_THIS(PBL_Flipper);
105
if (!SceneInfo->inEditor) {
106
self->visible = true;
107
self->scale.x = self->direction == FLIP_NONE ? 0x100 : -0x100;
108
self->drawGroup = 4;
109
self->active = ACTIVE_BOUNDS;
110
self->updateRange.x = 0x400000;
111
self->updateRange.y = 0x400000;
112
self->angle = -0x4000;
113
self->scale.y = 0x100;
114
self->flipperActive = true;
115
self->state = PBL_Flipper_State_AwaitFlip;
116
117
RSDK.SetModelAnimation(PBL_Flipper->modelFrames, &self->animator, 96, 0, true, 0);
118
}
119
}
120
121
void PBL_Flipper_StageLoad(void)
122
{
123
PBL_Flipper->modelFrames = RSDK.LoadMesh("Pinball/Flipper.bin", SCOPE_STAGE);
124
125
PBL_Flipper->sceneIndex = RSDK.Create3DScene("View:Pinball", 0x1000, SCOPE_STAGE);
126
127
PBL_Flipper->drawType = S3D_SOLIDCOLOR_SHADED_BLENDED_SCREEN;
128
129
PBL_Flipper->hitbox.left = -52;
130
PBL_Flipper->hitbox.top = -8;
131
PBL_Flipper->hitbox.right = 12;
132
PBL_Flipper->hitbox.bottom = 8;
133
134
PBL_Flipper->hitboxUnused.left = -52;
135
PBL_Flipper->hitboxUnused.top = -24;
136
PBL_Flipper->hitboxUnused.right = 12;
137
PBL_Flipper->hitboxUnused.bottom = 8;
138
139
PBL_Flipper->sfxFlipperStage = RSDK.GetSfx("Stage/Flipper.wav");
140
PBL_Flipper->sfxFlipper = RSDK.GetSfx("Pinball/Flipper.wav");
141
}
142
143
void PBL_Flipper_HandlePlayerInteractions(void)
144
{
145
RSDK_THIS(PBL_TargetBumper);
146
147
if (self->scale.y >= 0x80) {
148
int32 angle = self->angle >> 10;
149
int32 negAngle = 0;
150
if (self->direction == FLIP_X) {
151
negAngle = angle;
152
angle = -angle;
153
}
154
else {
155
negAngle = -angle;
156
angle = angle;
157
}
158
159
Vector2 originVel = { 0, 0 };
160
foreach_active(PBL_Player, player)
161
{
162
int32 posX = player->position.x;
163
int32 posY = player->position.y;
164
int32 velStoreX = player->velocity.x;
165
int32 velStoreY = player->velocity.y;
166
167
Zone_RotateOnPivot(&player->position, &self->position, angle);
168
Zone_RotateOnPivot(&player->velocity, &originVel, angle);
169
170
int32 velX = player->velocity.x;
171
int32 velY = player->velocity.y;
172
173
int32 distance = 0;
174
if (self->direction == FLIP_NONE)
175
distance = self->position.x - player->position.x;
176
else
177
distance = player->position.x - self->position.x;
178
int32 force = CLAMP((distance + 0x80000) >> 13, 16, 256);
179
180
switch (RSDK.CheckObjectCollisionBox(self, &PBL_Flipper->hitbox, player, &PBL_Player->outerBox, true)) {
181
case C_NONE:
182
player->position.x = posX;
183
player->position.y = posY;
184
player->velocity.x = velStoreX;
185
player->velocity.y = velStoreY;
186
break;
187
188
case C_TOP:
189
if (velY < 0) {
190
player->velocity.x = velStoreX;
191
player->velocity.y = velStoreY;
192
Zone_RotateOnPivot(&player->position, &self->position, negAngle);
193
}
194
else {
195
if (velY > 0)
196
velY >>= 2;
197
if (velY > 0x80000)
198
velY = 0x80000;
199
200
player->onGround = false;
201
202
if (velY > 0x40000)
203
player->velocity.x >>= 2;
204
205
if (self->state == PBL_Flipper_State_RiseFlipper && self->velocity.y == 0x2000) {
206
player->velocity.y -= (0xE0000 * force) >> 8;
207
player->onGround = false;
208
player->angle = 0;
209
}
210
211
Zone_RotateOnPivot(&player->position, &self->position, negAngle);
212
Zone_RotateOnPivot(&player->velocity, &originVel, negAngle);
213
}
214
break;
215
216
case C_LEFT:
217
if (velX < 0) {
218
player->velocity.x = velX;
219
}
220
else {
221
player->velocity.x = -(velX >> 2);
222
223
if (player->velocity.x <= -0x10000) {
224
if (player->velocity.x < -0x80000)
225
player->velocity.x = -0x80000;
226
227
player->velocity.y -= 0x20000;
228
}
229
else {
230
player->velocity.x = -0x10000;
231
player->velocity.y -= 0x20000;
232
}
233
234
Zone_RotateOnPivot(&player->position, &self->position, negAngle);
235
Zone_RotateOnPivot(&player->velocity, &originVel, negAngle);
236
}
237
break;
238
239
case C_RIGHT:
240
if (velX > 0) {
241
player->velocity.x = velX;
242
}
243
else {
244
player->velocity.x = -(velX >> 2);
245
246
if (player->velocity.x >= 0x10000) {
247
if (player->velocity.x > 0x80000)
248
player->velocity.x = 0x80000;
249
250
player->velocity.y -= 0x20000;
251
}
252
else {
253
player->velocity.x = 0x10000;
254
player->velocity.y -= 0x20000;
255
}
256
}
257
258
Zone_RotateOnPivot(&player->position, &self->position, negAngle);
259
Zone_RotateOnPivot(&player->velocity, &originVel, negAngle);
260
break;
261
262
case C_BOTTOM:
263
player->velocity.y = -(velY >> 2);
264
265
Zone_RotateOnPivot(&player->position, &self->position, negAngle);
266
Zone_RotateOnPivot(&player->velocity, &originVel, negAngle);
267
break;
268
269
default: break;
270
}
271
}
272
}
273
}
274
275
void PBL_Flipper_State_AwaitFlip(void)
276
{
277
RSDK_THIS(PBL_Flipper);
278
279
if (self->buttonDown) {
280
self->velocity.y = 0x2000;
281
self->state = PBL_Flipper_State_RiseFlipper;
282
RSDK.PlaySfx(PBL_Flipper->sfxFlipper, false, 255);
283
}
284
285
PBL_Flipper_HandlePlayerInteractions();
286
}
287
288
void PBL_Flipper_State_RiseFlipper(void)
289
{
290
RSDK_THIS(PBL_Flipper);
291
292
self->angle += self->velocity.y;
293
294
if (self->angle < 0x4000 || self->velocity.y < 0) {
295
if (self->velocity.y < 0x2000)
296
self->velocity.y += 0x400;
297
}
298
else {
299
self->angle = 0x4000;
300
self->velocity.y = -(self->velocity.y >> 2);
301
302
if (!self->buttonDown) {
303
self->velocity.y = -0x2000;
304
self->state = PBL_Flipper_State_LowerFlipper;
305
}
306
}
307
308
PBL_Flipper_HandlePlayerInteractions();
309
}
310
311
void PBL_Flipper_State_LowerFlipper(void)
312
{
313
RSDK_THIS(PBL_Flipper);
314
315
self->angle += self->velocity.y;
316
317
if (self->angle > -0x4000 || self->velocity.y > 0) {
318
if (self->velocity.y > -0x2000)
319
self->velocity.y -= 0x400;
320
}
321
else {
322
self->angle = -0x4000;
323
self->velocity.y = -(self->velocity.y >> 2);
324
325
if (self->velocity.y < 0x800) {
326
self->velocity.y = 0;
327
self->state = PBL_Flipper_State_AwaitFlip;
328
}
329
}
330
331
PBL_Flipper_HandlePlayerInteractions();
332
}
333
334
#if GAME_INCLUDE_EDITOR
335
void PBL_Flipper_EditorDraw(void) {}
336
337
void PBL_Flipper_EditorLoad(void)
338
{
339
RSDK_ACTIVE_VAR(PBL_Flipper, direction);
340
RSDK_ENUM_VAR("Left", FLIP_NONE);
341
RSDK_ENUM_VAR("Right", FLIP_X);
342
}
343
#endif
344
345
void PBL_Flipper_Serialize(void)
346
{
347
RSDK_EDITABLE_VAR(PBL_Flipper, VAR_UINT8, direction);
348
RSDK_EDITABLE_VAR(PBL_Flipper, VAR_UINT8, minCraneID);
349
RSDK_EDITABLE_VAR(PBL_Flipper, VAR_BOOL, retractable);
350
}
351
#endif
352
353