Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/SBZ/Bomb.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: Bomb Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectBomb *Bomb = NULL;
11
12
void Bomb_Update(void)
13
{
14
RSDK_THIS(Bomb);
15
StateMachine_Run(self->state);
16
}
17
18
void Bomb_LateUpdate(void) {}
19
20
void Bomb_StaticUpdate(void) {}
21
22
void Bomb_Draw(void)
23
{
24
RSDK_THIS(Bomb);
25
Vector2 drawPos;
26
27
if (self->state == Bomb_State_Explode) {
28
drawPos.x = self->position.x;
29
drawPos.y = self->fuseOffset + self->position.y;
30
RSDK.DrawSprite(&self->fuseAnimator, &drawPos, false);
31
}
32
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
33
}
34
35
void Bomb_Create(void *data)
36
{
37
RSDK_THIS(Bomb);
38
39
self->visible = true;
40
if (self->planeFilter > 0 && (((uint8)self->planeFilter - 1) & 2))
41
self->drawGroup = Zone->objectDrawGroup[1];
42
else
43
self->drawGroup = Zone->objectDrawGroup[0];
44
self->active = ACTIVE_BOUNDS;
45
self->updateRange.x = 0x800000;
46
self->updateRange.y = 0x800000;
47
if (data) {
48
RSDK.SetSpriteAnimation(Bomb->aniFrames, 4, &self->mainAnimator, true, 0);
49
self->state = Bomb_State_Shrapnel;
50
}
51
else {
52
self->startDir = self->direction;
53
self->startPos = self->position;
54
if (self->direction == FLIP_NONE)
55
self->velocity.x = -0x1000;
56
else
57
self->velocity.x = 0x1000;
58
self->drawFX |= FX_FLIP;
59
self->timer = 1536;
60
RSDK.SetSpriteAnimation(Bomb->aniFrames, 1, &self->mainAnimator, true, 0);
61
RSDK.SetSpriteAnimation(Bomb->aniFrames, 3, &self->fuseAnimator, true, 0);
62
self->state = Bomb_State_Init;
63
}
64
}
65
66
void Bomb_StageLoad(void)
67
{
68
if (RSDK.CheckSceneFolder("MMZ"))
69
Bomb->aniFrames = RSDK.LoadSpriteAnimation("MMZ/Bomb.bin", SCOPE_STAGE);
70
71
Bomb->hitboxHurt.left = -12;
72
Bomb->hitboxHurt.top = -18;
73
Bomb->hitboxHurt.right = 12;
74
Bomb->hitboxHurt.bottom = 18;
75
76
Bomb->hitboxRange.left = -96;
77
Bomb->hitboxRange.top = -96;
78
Bomb->hitboxRange.right = 96;
79
Bomb->hitboxRange.bottom = 96;
80
81
Bomb->hitboxShrapnel.left = -6;
82
Bomb->hitboxShrapnel.top = -6;
83
Bomb->hitboxShrapnel.right = 6;
84
Bomb->hitboxShrapnel.bottom = 6;
85
86
Bomb->sfxExplosion = RSDK.GetSfx("Stage/Explosion.wav");
87
88
DEBUGMODE_ADD_OBJ(Bomb);
89
}
90
91
void Bomb_DebugSpawn(void)
92
{
93
RSDK_THIS(Bomb);
94
CREATE_ENTITY(Bomb, NULL, self->position.x, self->position.y);
95
}
96
97
void Bomb_DebugDraw(void)
98
{
99
RSDK.SetSpriteAnimation(Bomb->aniFrames, 0, &DebugMode->animator, true, 0);
100
RSDK.DrawSprite(&DebugMode->animator, 0, false);
101
}
102
103
void Bomb_CheckOffScreen(void)
104
{
105
RSDK_THIS(Bomb);
106
107
if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {
108
self->position = self->startPos;
109
self->direction = self->startDir;
110
Bomb_Create(NULL);
111
}
112
}
113
114
void Bomb_CheckPlayerCollisions(void)
115
{
116
RSDK_THIS(Bomb);
117
118
foreach_active(Player, player)
119
{
120
if (self->planeFilter <= 0 || player->collisionPlane == ((self->planeFilter - 1) & 1)) {
121
if (self->state != Bomb_State_Explode) {
122
if (Player_CheckCollisionTouch(player, self, &Bomb->hitboxRange)) {
123
RSDK.SetSpriteAnimation(Bomb->aniFrames, 2, &self->mainAnimator, true, 0);
124
self->timer = 144;
125
self->state = Bomb_State_Explode;
126
}
127
}
128
if (Player_CheckCollisionTouch(player, self, &Bomb->hitboxHurt)) {
129
Player_Hurt(player, self);
130
}
131
}
132
}
133
}
134
135
void Bomb_State_Init(void)
136
{
137
RSDK_THIS(Bomb);
138
139
self->active = ACTIVE_NORMAL;
140
self->state = Bomb_State_Walk;
141
Bomb_State_Walk();
142
}
143
144
void Bomb_State_Walk(void)
145
{
146
RSDK_THIS(Bomb);
147
148
self->position.x += self->velocity.x;
149
150
if (!--self->timer) {
151
self->timer = 180;
152
self->state = Bomb_State_Idle;
153
}
154
else {
155
bool32 groundCollided = false;
156
if ((self->direction & FLIP_Y)) // RWall??? it should be roof right???
157
groundCollided = RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_RWALL, 0, 0, -0x100000, 2);
158
else
159
groundCollided = RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x100000, 2);
160
161
if (!groundCollided) {
162
self->timer = 180;
163
RSDK.SetSpriteAnimation(Bomb->aniFrames, 0, &self->mainAnimator, true, 0);
164
self->state = Bomb_State_Idle;
165
}
166
}
167
168
RSDK.ProcessAnimation(&self->mainAnimator);
169
170
Bomb_CheckPlayerCollisions();
171
Bomb_CheckOffScreen();
172
}
173
174
void Bomb_State_Idle(void)
175
{
176
RSDK_THIS(Bomb);
177
178
if (!--self->timer) {
179
self->direction ^= FLIP_X;
180
self->velocity.x = -self->velocity.x;
181
self->timer = 0x600;
182
RSDK.SetSpriteAnimation(Bomb->aniFrames, 1, &self->mainAnimator, true, 0);
183
self->state = Bomb_State_Walk;
184
}
185
186
RSDK.ProcessAnimation(&self->mainAnimator);
187
188
Bomb_CheckPlayerCollisions();
189
Bomb_CheckOffScreen();
190
}
191
192
void Bomb_State_Explode(void)
193
{
194
RSDK_THIS(Bomb);
195
196
if ((self->direction & FLIP_Y))
197
self->fuseOffset -= 0x1000;
198
else
199
self->fuseOffset += 0x1000;
200
201
if (--self->timer > 0) {
202
RSDK.ProcessAnimation(&self->mainAnimator);
203
RSDK.ProcessAnimation(&self->fuseAnimator);
204
Bomb_CheckPlayerCollisions();
205
Bomb_CheckOffScreen();
206
}
207
else {
208
RSDK.PlaySfx(Bomb->sfxExplosion, false, 255);
209
EntityBomb *debris = CREATE_ENTITY(Bomb, INT_TO_VOID(true), self->position.x, self->position.y);
210
debris->velocity.x = -0x20000;
211
debris->velocity.y = -0x30000;
212
debris->planeFilter = self->planeFilter;
213
debris->drawGroup = self->drawGroup;
214
215
debris = CREATE_ENTITY(Bomb, INT_TO_VOID(true), self->position.x, self->position.y);
216
debris->velocity.x = -0x10000;
217
debris->velocity.y = -0x20000;
218
debris->planeFilter = self->planeFilter;
219
debris->drawGroup = self->drawGroup;
220
221
debris = CREATE_ENTITY(Bomb, INT_TO_VOID(true), self->position.x, self->position.y);
222
debris->velocity.x = 0x20000;
223
debris->velocity.y = -0x30000;
224
debris->planeFilter = self->planeFilter;
225
debris->drawGroup = self->drawGroup;
226
227
debris = CREATE_ENTITY(Bomb, INT_TO_VOID(true), self->position.x, self->position.y);
228
debris->velocity.x = 0x10000;
229
debris->velocity.y = -0x20000;
230
debris->planeFilter = self->planeFilter;
231
debris->drawGroup = self->drawGroup;
232
233
EntityExplosion *explosion = CREATE_ENTITY(Explosion, INT_TO_VOID(EXPLOSION_ENEMY), self->position.x, self->position.y);
234
explosion->planeFilter = self->planeFilter;
235
explosion->drawGroup = self->drawGroup + 1;
236
237
destroyEntity(self);
238
}
239
}
240
241
void Bomb_State_Shrapnel(void)
242
{
243
RSDK_THIS(Bomb);
244
245
self->position.x += self->velocity.x;
246
self->position.y += self->velocity.y;
247
self->velocity.y += 0x1800;
248
if (RSDK.CheckOnScreen(self, &self->updateRange)) {
249
RSDK.ProcessAnimation(&self->mainAnimator);
250
251
foreach_active(Player, player)
252
{
253
if (self->planeFilter <= 0 || player->collisionPlane == ((self->planeFilter - 1) & 1)) {
254
if (Player_CheckCollisionTouch(player, self, &Bomb->hitboxShrapnel)) {
255
Player_ProjectileHurt(player, self);
256
}
257
}
258
}
259
}
260
else {
261
destroyEntity(self);
262
}
263
}
264
265
#if GAME_INCLUDE_EDITOR
266
void Bomb_EditorDraw(void) { Bomb_Draw(); }
267
268
void Bomb_EditorLoad(void)
269
{
270
Bomb->aniFrames = RSDK.LoadSpriteAnimation("MMZ/Bomb.bin", SCOPE_STAGE);
271
272
RSDK_ACTIVE_VAR(Bomb, planeFilter);
273
RSDK_ENUM_VAR("None", PLANEFILTER_NONE);
274
RSDK_ENUM_VAR("AL", PLANEFILTER_AL);
275
RSDK_ENUM_VAR("BL", PLANEFILTER_BL);
276
RSDK_ENUM_VAR("AH", PLANEFILTER_AH);
277
RSDK_ENUM_VAR("BH", PLANEFILTER_BH);
278
279
RSDK_ACTIVE_VAR(Bomb, direction);
280
RSDK_ENUM_VAR("Left", FLIP_NONE);
281
RSDK_ENUM_VAR("Right", FLIP_X);
282
RSDK_ENUM_VAR("Left (Flip Y)", FLIP_Y);
283
RSDK_ENUM_VAR("Right (Flip Y)", FLIP_XY);
284
}
285
#endif
286
287
void Bomb_Serialize(void)
288
{
289
RSDK_EDITABLE_VAR(Bomb, VAR_UINT8, direction);
290
RSDK_EDITABLE_VAR(Bomb, VAR_ENUM, planeFilter);
291
}
292
293