Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/UFO/UFO_Sphere.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: UFO_Sphere Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectUFO_Sphere *UFO_Sphere;
11
12
void UFO_Sphere_Update(void)
13
{
14
RSDK_THIS(UFO_Sphere);
15
16
StateMachine_Run(self->state);
17
18
RSDK.ProcessAnimation(&self->animator);
19
}
20
21
void UFO_Sphere_LateUpdate(void)
22
{
23
RSDK_THIS(UFO_Sphere);
24
25
int32 x = self->position.x >> 8;
26
int32 y = self->height >> 8;
27
int32 z = self->position.y >> 8;
28
29
Matrix *mat = &UFO_Camera->matWorld;
30
31
self->worldPos.x = mat->values[0][3] + (y * mat->values[0][1] >> 8) + (z * mat->values[0][2] >> 8) + (x * mat->values[0][0] >> 8);
32
self->worldPos.y = mat->values[1][3] + (y * mat->values[1][1] >> 8) + (z * mat->values[1][2] >> 8) + (x * mat->values[1][0] >> 8);
33
self->zdepth = mat->values[2][3] + (y * mat->values[2][1] >> 8) + (z * mat->values[2][2] >> 8) + (x * mat->values[2][0] >> 8);
34
}
35
36
void UFO_Sphere_StaticUpdate(void) {}
37
38
void UFO_Sphere_Draw(void)
39
{
40
RSDK_THIS(UFO_Sphere);
41
42
if (self->drawGroup == 4 && self->zdepth >= 0x100) {
43
self->direction = self->animator.frameID > 8;
44
self->drawPos.x = (ScreenInfo->center.x + (self->worldPos.x << 8) / self->zdepth) << 16;
45
self->drawPos.y = (ScreenInfo->center.y - (self->worldPos.y << 8) / self->zdepth) << 16;
46
self->scale.x = self->scaleFactor / self->zdepth;
47
self->scale.y = self->scaleFactor / self->zdepth;
48
}
49
50
RSDK.DrawSprite(&self->animator, &self->drawPos, true);
51
}
52
53
void UFO_Sphere_Create(void *data)
54
{
55
RSDK_THIS(UFO_Sphere);
56
57
if (!SceneInfo->inEditor) {
58
self->visible = true;
59
self->drawFX = FX_SCALE | FX_FLIP;
60
self->drawGroup = 4;
61
self->active = ACTIVE_RBOUNDS;
62
self->updateRange.x = 0x400;
63
self->updateRange.y = 0x400;
64
65
self->scaleFactor = 0x1000000;
66
67
if (!self->height)
68
self->height = UFO_Sphere->defaultHeights[self->type];
69
self->height <<= 16;
70
71
switch (self->behavior) {
72
default:
73
case UFO_SPHERE_B_NONE: // static
74
self->state = UFO_Sphere_State_Fixed;
75
break;
76
77
case UFO_SPHERE_B_BOUNCE:
78
self->velocity.y = 0x20000;
79
self->state = UFO_Sphere_State_Bouncing;
80
break;
81
82
case UFO_SPHERE_B_MOVE:
83
self->amplitude.x >>= 8;
84
self->amplitude.y >>= 8;
85
self->startPos.x = self->position.x;
86
self->startPos.y = self->position.y;
87
self->startHeight = self->height;
88
self->state = UFO_Sphere_State_Moving;
89
90
Matrix matrix;
91
RSDK.MatrixRotateX(&matrix, self->matAngle.x);
92
RSDK.MatrixRotateY(&self->matrix, self->matAngle.y);
93
RSDK.MatrixMultiply(&self->matrix, &matrix, &self->matrix);
94
break;
95
}
96
97
RSDK.SetSpriteAnimation(UFO_Sphere->aniFrames, self->type, &self->animator, true, 0);
98
}
99
}
100
101
void UFO_Sphere_StageLoad(void)
102
{
103
UFO_Sphere->aniFrames = RSDK.LoadSpriteAnimation("SpecialUFO/Spheres.bin", SCOPE_STAGE);
104
105
UFO_Sphere->sfxMachSpeed = RSDK.GetSfx("Special/MachSpeed.wav");
106
UFO_Sphere->sfxLedgeBreak = RSDK.GetSfx("Stage/LedgeBreak.wav");
107
}
108
109
void UFO_Sphere_State_Fixed(void)
110
{
111
RSDK_THIS(UFO_Sphere);
112
113
switch (self->type) {
114
case UFO_SPHERE_BLUE: {
115
foreach_active(UFO_Player, player)
116
{
117
int32 rx = (self->position.x - player->position.x) >> 16;
118
int32 ry = (self->height - player->height - 0xA0000) >> 16;
119
int32 rz = (self->position.y - player->position.y) >> 16;
120
121
if (rx * rx + ry * ry + rz * rz < UFO_Player->maxSpeed >> 9) {
122
self->drawGroup = 12;
123
124
self->state = UFO_Sphere_State_Collected;
125
UFO_Setup_PlaySphereSfx();
126
}
127
}
128
129
if (UFO_Setup->machLevel == 2)
130
self->animator.speed = 1;
131
break;
132
}
133
134
case UFO_SPHERE_RED:
135
// unused
136
break;
137
138
case UFO_SPHERE_MINE: {
139
foreach_active(UFO_Player, player)
140
{
141
if (player->state != UFO_Player_State_Trip && player->state != UFO_Player_State_Springboard
142
&& player->state != UFO_Player_State_UFOCaught_Charge && player->state != UFO_Player_State_UFOCaught_Released) {
143
int32 rx = (self->position.x - player->position.x) >> 16;
144
int32 ry = (self->height - player->height - 0xA0000) >> 16;
145
int32 rz = (self->position.y - player->position.y) >> 16;
146
147
if (rx * rx + ry * ry + rz * rz < 0x180) {
148
RSDK.SetModelAnimation(UFO_Player->tumbleModel, &player->animator, 80, 0, false, 0);
149
150
player->state = UFO_Player_State_Trip;
151
152
if (UFO_Setup->rings > 0)
153
RSDK.PlaySfx(UFO_Player->sfxLoseRings, false, 255);
154
155
UFO_Ring_LoseRings(player);
156
157
RSDK.SetSpriteAnimation(UFO_Sphere->aniFrames, 4, &self->animator, true, 0);
158
self->scaleFactor = 0x1800000;
159
self->state = UFO_Sphere_State_AnimateAndDestroy;
160
RSDK.PlaySfx(UFO_Sphere->sfxLedgeBreak, false, 255);
161
}
162
}
163
}
164
break;
165
}
166
case UFO_SPHERE_SPIKES: {
167
foreach_active(UFO_Player, player)
168
{
169
if (player->state != UFO_Player_State_Trip && player->state != UFO_Player_State_Springboard
170
&& player->state != UFO_Player_State_UFOCaught_Charge && player->state != UFO_Player_State_UFOCaught_Released) {
171
int32 rx = (self->position.x - player->position.x) >> 16;
172
int32 ry = (self->height - player->height - 0xA0000) >> 16;
173
int32 rz = (self->position.y - player->position.y) >> 16;
174
175
if (rx * rx + ry * ry + rz * rz < 0x180) {
176
RSDK.SetModelAnimation(UFO_Player->tumbleModel, &player->animator, 80, 0, false, 0);
177
178
player->state = UFO_Player_State_Trip;
179
180
if (UFO_Setup->rings > 0)
181
RSDK.PlaySfx(UFO_Player->sfxLoseRings, false, 255);
182
183
UFO_Ring_LoseRings(player);
184
}
185
}
186
}
187
break;
188
}
189
}
190
}
191
192
void UFO_Sphere_State_Bouncing(void)
193
{
194
RSDK_THIS(UFO_Sphere);
195
196
self->velocity.y -= 0x3800;
197
self->height += self->velocity.y;
198
199
if (self->height < 0xC0000) {
200
self->velocity.y = 0x20000;
201
self->height = 0xC0000;
202
}
203
204
UFO_Sphere_State_Fixed();
205
}
206
207
void UFO_Sphere_State_Moving(void)
208
{
209
RSDK_THIS(UFO_Sphere);
210
211
Matrix *m = &self->matrix;
212
213
self->position.x = self->amplitude.x * RSDK.Cos256(self->angle + (UFO_Setup->timer << self->speed));
214
self->position.y = self->amplitude.y * RSDK.Sin256(self->angle + (UFO_Setup->timer << self->speed));
215
self->height = 0;
216
217
self->position.x = m->values[0][3] + (self->position.y >> 8) * m->values[0][2] + m->values[0][0] * (self->position.x >> 8);
218
self->height = m->values[1][3] + (self->position.y >> 8) * m->values[1][2] + m->values[1][0] * (self->position.x >> 8);
219
self->position.y = m->values[2][3] + (self->position.y >> 8) * m->values[2][2] + m->values[2][0] * (self->position.x >> 8)
220
+ m->values[2][1] * (self->height >> 8);
221
222
self->position.x += self->startPos.x;
223
self->position.y += self->startPos.y;
224
self->height += self->startHeight;
225
226
UFO_Sphere_State_Fixed();
227
}
228
229
void UFO_Sphere_State_Collected(void)
230
{
231
RSDK_THIS(UFO_Sphere);
232
233
self->drawPos.x += ((((ScreenInfo->center.x - 38) << 16) - self->drawPos.x) >> 3);
234
self->drawPos.y += ((0x1C0000 - self->drawPos.y) >> 3);
235
236
self->scale.x = self->scale.x + ((0x80 - self->scale.x) >> 3);
237
self->scale.y = self->scale.x + ((0x80 - self->scale.x) >> 3);
238
239
if (self->drawPos.y < 0x200000) {
240
++UFO_Setup->machPoints;
241
UFO_HUD_CheckLevelUp();
242
243
self->timer = UFO_Setup->timer;
244
self->visible = false;
245
self->state = UFO_Sphere_State_HandleRespawn;
246
}
247
}
248
249
void UFO_Sphere_State_HandleRespawn(void)
250
{
251
RSDK_THIS(UFO_Sphere);
252
253
if (abs(self->timer - UFO_Setup->timer) > 240) {
254
self->visible = true;
255
self->drawGroup = 4;
256
257
switch (self->behavior) {
258
default:
259
case UFO_SPHERE_B_NONE: self->state = UFO_Sphere_State_Fixed; break;
260
261
case UFO_SPHERE_B_BOUNCE: self->state = UFO_Sphere_State_Bouncing; break;
262
263
case UFO_SPHERE_B_MOVE: self->state = UFO_Sphere_State_Moving; break;
264
}
265
}
266
}
267
268
void UFO_Sphere_State_AnimateAndDestroy(void)
269
{
270
RSDK_THIS(UFO_Sphere);
271
272
if (self->animator.frameID == self->animator.frameCount - 1)
273
destroyEntity(self);
274
}
275
276
#if GAME_INCLUDE_EDITOR
277
void UFO_Sphere_EditorDraw(void)
278
{
279
RSDK_THIS(UFO_Sphere);
280
281
RSDK.SetSpriteAnimation(UFO_Sphere->aniFrames, 5, &self->animator, true, self->type);
282
283
RSDK.DrawSprite(&self->animator, NULL, false);
284
285
if (showGizmos() && self->behavior == UFO_SPHERE_B_MOVE) {
286
Vector2 amplitude;
287
288
amplitude.x = self->amplitude.x >> 8;
289
amplitude.y = self->amplitude.y >> 8;
290
self->startPos.x = self->position.x;
291
self->startPos.y = self->position.y;
292
293
self->inkEffect = INK_BLEND;
294
295
Vector2 start, end;
296
297
// start pos
298
self->position.x = amplitude.x * RSDK.Cos256(self->angle) + self->startPos.x;
299
self->position.y = amplitude.y * RSDK.Sin256(self->angle) + self->startPos.y;
300
RSDK.DrawSprite(&self->animator, NULL, false);
301
302
// right max
303
self->position.x = amplitude.x * RSDK.Cos256(0x00) + self->startPos.x;
304
self->position.y = amplitude.y * RSDK.Sin256(0x00) + self->startPos.y;
305
start = self->position;
306
RSDK.DrawSprite(&self->animator, NULL, false);
307
308
// left max
309
self->position.x = amplitude.x * RSDK.Cos256(0x80) + self->startPos.x;
310
self->position.y = amplitude.y * RSDK.Sin256(0x80) + self->startPos.y;
311
end = self->position;
312
RSDK.DrawSprite(&self->animator, NULL, false);
313
314
DrawHelpers_DrawArrow(start.x, start.y, end.x, end.y, 0x00FF00, INK_NONE, 0xFF);
315
DrawHelpers_DrawArrow(end.x, end.y, start.x, start.y, 0x00FF00, INK_NONE, 0xFF);
316
317
self->inkEffect = INK_NONE;
318
}
319
}
320
321
void UFO_Sphere_EditorLoad(void)
322
{
323
UFO_Sphere->aniFrames = RSDK.LoadSpriteAnimation("SpecialUFO/Spheres.bin", SCOPE_STAGE);
324
325
RSDK_ACTIVE_VAR(UFO_Sphere, type);
326
RSDK_ENUM_VAR("Blue", UFO_SPHERE_BLUE);
327
RSDK_ENUM_VAR("Red (Unused)", UFO_SPHERE_RED);
328
RSDK_ENUM_VAR("Mine", UFO_SPHERE_MINE);
329
RSDK_ENUM_VAR("Spikes", UFO_SPHERE_SPIKES);
330
331
RSDK_ACTIVE_VAR(UFO_Sphere, behavior);
332
RSDK_ENUM_VAR("None", UFO_SPHERE_B_NONE);
333
RSDK_ENUM_VAR("Bouncing", UFO_SPHERE_B_BOUNCE);
334
RSDK_ENUM_VAR("Moving", UFO_SPHERE_B_MOVE);
335
}
336
#endif
337
338
void UFO_Sphere_Serialize(void)
339
{
340
RSDK_EDITABLE_VAR(UFO_Sphere, VAR_ENUM, type);
341
RSDK_EDITABLE_VAR(UFO_Sphere, VAR_ENUM, behavior);
342
RSDK_EDITABLE_VAR(UFO_Sphere, VAR_ENUM, height);
343
RSDK_EDITABLE_VAR(UFO_Sphere, VAR_ENUM, speed);
344
RSDK_EDITABLE_VAR(UFO_Sphere, VAR_ENUM, angle);
345
RSDK_EDITABLE_VAR(UFO_Sphere, VAR_VECTOR2, matAngle);
346
RSDK_EDITABLE_VAR(UFO_Sphere, VAR_VECTOR2, amplitude);
347
}
348
349