Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/FBZ/FBZTrash.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: FBZTrash Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectFBZTrash *FBZTrash;
11
12
void FBZTrash_Update(void)
13
{
14
RSDK_THIS(FBZTrash);
15
16
StateMachine_Run(self->state);
17
}
18
19
void FBZTrash_LateUpdate(void) {}
20
21
void FBZTrash_StaticUpdate(void) {}
22
23
void FBZTrash_Draw(void)
24
{
25
RSDK_THIS(FBZTrash);
26
27
RSDK.DrawSprite(&self->animator, NULL, false);
28
}
29
30
void FBZTrash_Create(void *data)
31
{
32
RSDK_THIS(FBZTrash);
33
34
if (!SceneInfo->inEditor) {
35
self->active = ACTIVE_BOUNDS;
36
self->visible = true;
37
self->drawFX = FX_FLIP;
38
39
if (data) {
40
self->type = VOID_TO_INT(data);
41
self->drawGroup = Zone->objectDrawGroup[0];
42
43
self->hitbox.left = -8;
44
self->hitbox.top = -8;
45
self->hitbox.right = 8;
46
self->hitbox.bottom = 8;
47
48
self->updateRange.x = 0x800000;
49
self->updateRange.y = 0x800000;
50
self->state = FBZTrash_State_ReactMagnet;
51
}
52
else {
53
self->drawGroup = Zone->objectDrawGroup[1];
54
self->updateRange.x = 0x800000;
55
self->updateRange.y = 0x200000;
56
self->onGround = true;
57
58
self->direction = RSDK.Rand(0, 2);
59
RSDK.SetSpriteAnimation(FBZTrash->aniFrames, 0, &self->animator, true, self->frameID);
60
self->state = FBZTrash_State_LooseTrash;
61
}
62
}
63
}
64
65
void FBZTrash_StageLoad(void) { FBZTrash->aniFrames = RSDK.LoadSpriteAnimation("FBZ/Trash.bin", SCOPE_STAGE); }
66
67
void FBZTrash_SummonOrbinautOrbs(EntityFBZTrash *trashPtr, int32 angle)
68
{
69
EntityFBZTrash *trash = CREATE_ENTITY(FBZTrash, INT_TO_VOID(FBZTRASH_ORB), trashPtr->position.x, trashPtr->position.y);
70
71
trash->position.x += RSDK.Cos1024(angle) << 10;
72
trash->position.y += RSDK.Sin1024(angle) << 10;
73
trash->targetPos = trash->position;
74
int32 size = BigSqueeze->crusherX[BIGSQUEEZE_CRUSHER_R] - BigSqueeze->crusherX[BIGSQUEEZE_CRUSHER_L];
75
trash->position.x = (RSDK.Rand(0, size >> 16) << 16) + BigSqueeze->crusherX[BIGSQUEEZE_CRUSHER_L];
76
trash->position.y = BigSqueeze->boundsB - 0x80000;
77
trash->parent = trashPtr;
78
trash->startPos = trash->position;
79
trash->angle = angle;
80
trash->radius = 10;
81
trash->state = FBZTrash_State_ReactMagnet;
82
83
RSDK.SetSpriteAnimation(FBZTrash->aniFrames, 5, &trash->animator, true, RSDK.Rand(0, 2));
84
}
85
86
void FBZTrash_SummonOrbinaut(int32 x, int32 y)
87
{
88
EntityFBZTrash *trash = CREATE_ENTITY(FBZTrash, INT_TO_VOID(FBZTRASH_ORBINAUT), x, y);
89
FBZTrash_SummonOrbinautOrbs(trash, 0);
90
FBZTrash_SummonOrbinautOrbs(trash, 512);
91
92
trash->targetPos = trash->position;
93
int32 size = BigSqueeze->crusherX[BIGSQUEEZE_CRUSHER_R] - BigSqueeze->crusherX[BIGSQUEEZE_CRUSHER_L];
94
trash->position.x = (RSDK.Rand(0, size >> 16) << 16) + BigSqueeze->crusherX[BIGSQUEEZE_CRUSHER_L];
95
trash->position.y = BigSqueeze->boundsB - 0x80000;
96
trash->state = FBZTrash_State_ReactMagnet;
97
trash->startPos = trash->position;
98
99
RSDK.SetSpriteAnimation(FBZTrash->aniFrames, 1, &trash->animator, true, (x >> 17) & 1);
100
}
101
102
void FBZTrash_State_LooseTrash(void)
103
{
104
RSDK_THIS(FBZTrash);
105
106
if (!self->onGround) {
107
self->velocity.y += 0x3800;
108
self->position.x += self->velocity.x;
109
self->position.y += self->velocity.y;
110
}
111
112
if (self->velocity.y >= -0x8000) {
113
foreach_active(FBZTrash, trash)
114
{
115
if (trash != self) {
116
int32 rx = (self->position.x - trash->position.x) >> 16;
117
int32 ry = (self->position.y - trash->position.y) >> 16;
118
119
if (rx * rx + ry * ry < 0x120) {
120
if (BigSqueeze->isCrushing)
121
self->rumbleMove = (self->rumbleMove + trash->rumbleMove) >> 1;
122
else
123
self->rumbleMove >>= 1;
124
125
if (self->rumbleMove <= 0) {
126
self->onGround = true;
127
}
128
else {
129
int32 angle = RSDK.ATan2(rx, ry);
130
self->velocity.x = MIN(self->rumbleMove << 6, 640) * RSDK.Cos256(angle);
131
self->velocity.y = MIN(self->rumbleMove << 6, 640) * RSDK.Sin256(angle + RSDK.Rand(-32, 32));
132
self->onGround = false;
133
}
134
}
135
}
136
}
137
}
138
139
if (self->position.y < BigSqueeze->boundsB - 0xC0000)
140
self->position.y = BigSqueeze->boundsB - 0xC0000;
141
142
foreach_active(BigSqueeze, boss)
143
{
144
switch (boss->type) {
145
default: break;
146
147
case BIGSQUEEZE_BOSS:
148
if (self->position.y > boss->position.y + 0xC00000) {
149
self->position.y = boss->position.y + 0xC00000;
150
self->velocity.y = -abs(self->velocity.y >> 1);
151
}
152
break;
153
154
case BIGSQUEEZE_CRUSHER_L:
155
if (self->position.x < boss->position.x + 0x180000) {
156
self->position.x = boss->position.x + 0x180000;
157
self->velocity.x = 5 * boss->velocity.x;
158
if (self->onGround && BigSqueeze->isCrushing) {
159
self->rumbleMove = 128;
160
self->onGround = false;
161
}
162
}
163
break;
164
165
case BIGSQUEEZE_CRUSHER_R:
166
if (self->position.x > boss->position.x - 0x180000) {
167
self->position.x = boss->position.x - 0x180000;
168
self->velocity.x = 5 * boss->velocity.x;
169
if (self->onGround && BigSqueeze->isCrushing) {
170
self->rumbleMove = 128;
171
self->onGround = false;
172
}
173
}
174
break;
175
}
176
}
177
}
178
179
void FBZTrash_State_ReactMagnet(void)
180
{
181
RSDK_THIS(FBZTrash);
182
183
self->startPos.y -= 0x8000;
184
self->position.x = self->startPos.x + RSDK.Rand(-0x20000, 0x20000);
185
self->position.y = self->startPos.y + RSDK.Rand(-0x20000, 0x20000);
186
187
if (++self->timer == 16) {
188
self->timer = 0;
189
self->velocity.x = (self->targetPos.x - self->position.x) >> 5;
190
self->velocity.y = -0x80000;
191
self->state = FBZTrash_State_MoveToTarget;
192
}
193
}
194
195
void FBZTrash_State_MoveToTarget(void)
196
{
197
RSDK_THIS(FBZTrash);
198
199
self->velocity.y += 0x3800;
200
self->position.x += self->velocity.x;
201
self->position.y += self->velocity.y;
202
203
++self->timer;
204
if (self->velocity.y >= 0) {
205
if (self->position.y > self->targetPos.y)
206
self->position.y = self->targetPos.y;
207
}
208
209
if (self->velocity.x <= 0) {
210
if (self->position.x < self->targetPos.x) {
211
self->velocity.x = 0;
212
self->position.x = self->targetPos.x;
213
}
214
}
215
else if (self->position.x > self->targetPos.x) {
216
self->velocity.x = 0;
217
self->position.x = self->targetPos.x;
218
}
219
220
if (self->timer == 60) {
221
self->timer = 0;
222
switch (self->type) {
223
default: break;
224
case FBZTRASH_ORB: self->state = FBZTrash_State_OrbinautOrb; break;
225
case FBZTRASH_ORBINAUT: self->state = FBZTrash_State_OrbinautMove; break;
226
}
227
}
228
}
229
230
void FBZTrash_State_OrbinautOrb(void)
231
{
232
RSDK_THIS(FBZTrash);
233
EntityFBZTrash *trash = self->parent;
234
235
int32 angle = 0;
236
if (trash->type == FBZTRASH_ORB) {
237
self->angle = (self->angle + 8) & 0x3FF;
238
angle = RSDK.Sin256(self->angle) >> 2;
239
}
240
else if (trash->type == FBZTRASH_ORBINAUT) {
241
self->angle = (self->angle + 16) & 0x3FF;
242
angle = self->angle;
243
}
244
245
self->position.x = trash->position.x + (RSDK.Cos1024(angle) << self->radius);
246
self->position.y = trash->position.y + (RSDK.Sin1024(angle) << self->radius);
247
}
248
249
void FBZTrash_State_OrbinautMove(void)
250
{
251
RSDK_THIS(FBZTrash);
252
253
EntityPlayer *targetPlayer = Player_GetNearestPlayer();
254
self->angle = RSDK.ATan2(self->position.x - targetPlayer->position.x, self->position.y - targetPlayer->position.y);
255
self->velocity.x = RSDK.Cos256(self->angle) << 8;
256
self->velocity.y = RSDK.Sin256(self->angle) << 8;
257
self->direction = self->position.x >= targetPlayer->position.x;
258
self->position.x -= self->velocity.x;
259
self->position.y -= self->velocity.y;
260
261
foreach_active(Player, player)
262
{
263
if (Player_CheckCollisionTouch(player, self, &self->hitbox) && Player_CheckBadnikBreak(player, self, true)) {
264
foreach_all(Animals, animals) { destroyEntity(animals); }
265
266
#if MANIA_USE_PLUS
267
if (player->state != Player_State_MightyHammerDrop)
268
player->velocity.y = -0x40000;
269
#endif
270
}
271
}
272
}
273
274
#if GAME_INCLUDE_EDITOR
275
void FBZTrash_EditorDraw(void)
276
{
277
RSDK_THIS(FBZTrash);
278
279
self->updateRange.x = 0x800000;
280
self->updateRange.y = 0x800000;
281
switch (self->type) {
282
default: RSDK.SetSpriteAnimation(-1, 0, &self->animator, true, 0); break;
283
284
case FBZTRASH_TRASH:
285
self->updateRange.x = 0x800000;
286
self->updateRange.y = 0x200000;
287
RSDK.SetSpriteAnimation(FBZTrash->aniFrames, 0, &self->animator, true, self->frameID);
288
break;
289
}
290
291
FBZTrash_Draw();
292
}
293
294
void FBZTrash_EditorLoad(void)
295
{
296
FBZTrash->aniFrames = RSDK.LoadSpriteAnimation("FBZ/Trash.bin", SCOPE_STAGE);
297
298
RSDK_ACTIVE_VAR(FBZTrash, type);
299
RSDK_ENUM_VAR("Loose Trash", FBZTRASH_TRASH);
300
// RSDK_ENUM_VAR("(Unused)", FBZTRASH_UNUSED);
301
// RSDK_ENUM_VAR("Orbinaut Orb", FBZTRASH_ORB);
302
// RSDK_ENUM_VAR("Orbinaut", FBZTRASH_ORBINAUT);
303
}
304
#endif
305
306
void FBZTrash_Serialize(void)
307
{
308
RSDK_EDITABLE_VAR(FBZTrash, VAR_ENUM, type);
309
RSDK_EDITABLE_VAR(FBZTrash, VAR_ENUM, frameID);
310
}
311
312