Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/PGZ/IceBomba.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: IceBomba Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectIceBomba *IceBomba;
11
12
void IceBomba_Update(void)
13
{
14
RSDK_THIS(IceBomba);
15
16
StateMachine_Run(self->state);
17
}
18
19
void IceBomba_LateUpdate(void) {}
20
21
void IceBomba_StaticUpdate(void) {}
22
23
void IceBomba_Draw(void)
24
{
25
RSDK_THIS(IceBomba);
26
27
Vector2 drawPos = self->position;
28
drawPos.x += 0x40000;
29
drawPos.y += 0x1A0000;
30
31
int32 dirStore = self->direction;
32
self->direction = FLIP_NONE;
33
RSDK.DrawSprite(&self->bombAnimator, &drawPos, false);
34
RSDK.DrawSprite(&self->bodyAnimator, NULL, false);
35
36
self->direction = dirStore;
37
self->inkEffect = INK_ALPHA;
38
RSDK.DrawSprite(&self->wingAnimator, NULL, false);
39
40
self->inkEffect = INK_NONE;
41
}
42
43
void IceBomba_Create(void *data)
44
{
45
RSDK_THIS(IceBomba);
46
47
self->visible = true;
48
self->drawGroup = Zone->objectDrawGroup[0];
49
50
if (!SceneInfo->inEditor) {
51
self->dip <<= 7;
52
self->drawFX |= FX_FLIP;
53
54
if (data) {
55
self->active = ACTIVE_NORMAL;
56
self->updateRange.x = 0x400000;
57
self->updateRange.y = 0x800000;
58
RSDK.SetSpriteAnimation(IceBomba->aniFrames, 2, &self->bodyAnimator, true, 0);
59
self->state = IceBomba_State_Bomb;
60
}
61
else {
62
self->active = ACTIVE_BOUNDS;
63
self->alpha = 0x80;
64
self->startDist = self->dist;
65
self->updateRange.x = (self->dist + 0x80) << 16;
66
self->updateRange.y = (self->dip + 0x8000) << 8;
67
self->startPos = self->position;
68
RSDK.SetSpriteAnimation(IceBomba->aniFrames, 0, &self->bodyAnimator, true, 0);
69
RSDK.SetSpriteAnimation(IceBomba->aniFrames, 1, &self->wingAnimator, true, 0);
70
RSDK.SetSpriteAnimation(IceBomba->aniFrames, 2, &self->bombAnimator, true, 0);
71
72
self->direction = self->dir;
73
if (self->dir) {
74
self->bodyAnimator.frameID = 4;
75
self->bombAnimator.frameID = 4;
76
}
77
else {
78
self->bodyAnimator.frameID = 0;
79
self->bombAnimator.frameID = 0;
80
}
81
82
self->state = IceBomba_State_Init;
83
}
84
}
85
}
86
87
void IceBomba_StageLoad(void)
88
{
89
if (RSDK.CheckSceneFolder("PSZ1")) // PGZ1 doesn't have this badnik anywhere, the anim file doesn't even exist in the files...
90
IceBomba->aniFrames = RSDK.LoadSpriteAnimation("PSZ1/IceBomba.bin", SCOPE_STAGE);
91
else if (RSDK.CheckSceneFolder("PSZ2"))
92
IceBomba->aniFrames = RSDK.LoadSpriteAnimation("PSZ2/IceBomba.bin", SCOPE_STAGE);
93
94
IceBomba->hitboxBadnik.left = -12;
95
IceBomba->hitboxBadnik.top = -12;
96
IceBomba->hitboxBadnik.right = 12;
97
IceBomba->hitboxBadnik.bottom = 12;
98
99
IceBomba->hitboxBomb.left = -16;
100
IceBomba->hitboxBomb.top = -16;
101
IceBomba->hitboxBomb.right = 16;
102
IceBomba->hitboxBomb.bottom = 16;
103
104
IceBomba->hitboxRange.left = -12;
105
IceBomba->hitboxRange.top = 64;
106
IceBomba->hitboxRange.right = 12;
107
IceBomba->hitboxRange.bottom = 128;
108
109
IceBomba->sfxExplosion = RSDK.GetSfx("Stage/Explosion.wav");
110
IceBomba->sfxFreeze = RSDK.GetSfx("PSZ/Freeze.wav");
111
112
DEBUGMODE_ADD_OBJ(IceBomba);
113
}
114
115
void IceBomba_DebugDraw(void)
116
{
117
RSDK.SetSpriteAnimation(IceBomba->aniFrames, 0, &DebugMode->animator, true, 0);
118
RSDK.DrawSprite(&DebugMode->animator, NULL, false);
119
}
120
121
void IceBomba_DebugSpawn(void)
122
{
123
RSDK_THIS(IceBomba);
124
125
CREATE_ENTITY(IceBomba, NULL, self->position.x, self->position.y);
126
}
127
128
void IceBomba_HandlePlayerCollisions(void)
129
{
130
RSDK_THIS(IceBomba);
131
132
int32 storeDir = self->direction;
133
self->direction = FLIP_NONE;
134
135
foreach_active(Player, player)
136
{
137
if (Player_CheckBadnikTouch(player, self, &IceBomba->hitboxBadnik)) {
138
if (Player_CheckBadnikBreak(player, self, false)) {
139
if (self->state != IceBomba_State_FlyAway) {
140
EntityIceBomba *bomb = CREATE_ENTITY(IceBomba, INT_TO_VOID(true), self->position.x, self->position.y);
141
if (self->direction)
142
bomb->position.x -= 0x40000;
143
else
144
bomb->position.x += 0x40000;
145
bomb->position.y += 0x1A0000;
146
bomb->direction = self->direction;
147
}
148
149
destroyEntity(self);
150
}
151
}
152
else if (self->state != IceBomba_State_FlyAway) {
153
Vector2 storePos = self->position;
154
self->position.x += 0x40000 * (self->direction ? -1 : 1);
155
self->position.y += 0x1A0000;
156
157
if (Player_CheckCollisionTouch(player, self, &IceBomba->hitboxBomb)) {
158
RSDK.PlaySfx(IceBomba->sfxExplosion, false, 0xFF);
159
CREATE_ENTITY(Explosion, INT_TO_VOID(EXPLOSION_ENEMY), self->position.x, self->position.y)->drawGroup = Zone->objectDrawGroup[1];
160
RSDK.SetSpriteAnimation(-1, 0, &self->bombAnimator, true, 0);
161
self->state = IceBomba_State_FlyAway;
162
Ice_FreezePlayer(player);
163
}
164
165
self->position = storePos;
166
}
167
}
168
169
self->direction = storeDir;
170
}
171
172
void IceBomba_State_Init(void)
173
{
174
RSDK_THIS(IceBomba);
175
176
self->active = ACTIVE_NORMAL;
177
self->angle = 0;
178
self->direction = self->dir;
179
self->startDir = self->dir;
180
self->velocity.x = 0x8000 * (self->dir ? 1 : -1);
181
182
self->state = IceBomba_State_Flying;
183
IceBomba_State_Flying();
184
}
185
186
void IceBomba_CheckOffScreen(void)
187
{
188
RSDK_THIS(IceBomba);
189
190
if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {
191
self->dip >>= 7;
192
self->position = self->startPos;
193
IceBomba_Create(NULL);
194
}
195
}
196
197
void IceBomba_State_Flying(void)
198
{
199
RSDK_THIS(IceBomba);
200
201
RSDK.ProcessAnimation(&self->wingAnimator);
202
203
self->angle += 4;
204
205
self->position.x += self->velocity.x;
206
self->position.y = self->startPos.y + self->dip * RSDK.Sin1024(self->angle);
207
208
if (--self->startDist <= 0) {
209
RSDK.SetSpriteAnimation(-1, 1, &self->wingAnimator, true, 0);
210
self->state = IceBomba_State_Turning;
211
}
212
213
foreach_active(Player, player)
214
{
215
if (Player_CheckCollisionTouch(player, self, &IceBomba->hitboxRange)) {
216
EntityIceBomba *bomb = CREATE_ENTITY(IceBomba, INT_TO_VOID(true), self->position.x, self->position.y);
217
bomb->position.x += 0x40000 * (self->direction ? -1 : 1);
218
bomb->position.y += 0x1A0000;
219
bomb->direction = self->direction;
220
RSDK.SetSpriteAnimation(-1, 0, &self->bombAnimator, true, 0);
221
self->state = IceBomba_State_FlyAway;
222
foreach_break;
223
}
224
}
225
226
IceBomba_HandlePlayerCollisions();
227
IceBomba_CheckOffScreen();
228
}
229
230
void IceBomba_State_Turning(void)
231
{
232
RSDK_THIS(IceBomba);
233
234
self->angle += 4;
235
236
self->position.x += self->velocity.x;
237
self->position.y = self->dip * RSDK.Sin1024(self->angle) + self->startPos.y;
238
self->velocity.x += 0x1000 * (self->direction ? -1 : 1);
239
240
int32 animTimer = ++self->bodyAnimator.timer;
241
if (self->direction) {
242
if (animTimer >= 3) {
243
--self->bombAnimator.frameID;
244
--self->bodyAnimator.frameID;
245
self->bodyAnimator.timer = 0;
246
247
if (self->bodyAnimator.frameID <= 0) {
248
self->direction ^= FLIP_X;
249
self->startDist = 2 * self->dist;
250
self->velocity.x = 0x8000 * (self->direction ? 1 : -1);
251
RSDK.SetSpriteAnimation(IceBomba->aniFrames, 1, &self->wingAnimator, true, 0);
252
self->state = IceBomba_State_Flying;
253
}
254
}
255
}
256
else if (animTimer >= 3) {
257
++self->bombAnimator.frameID;
258
++self->bodyAnimator.frameID;
259
self->bodyAnimator.timer = 0;
260
if (self->bodyAnimator.frameID >= 4) {
261
self->direction ^= FLIP_X;
262
self->startDist = 2 * self->dist;
263
self->velocity.x = 0x8000;
264
RSDK.SetSpriteAnimation(IceBomba->aniFrames, 1, &self->wingAnimator, true, 0);
265
self->state = IceBomba_State_Flying;
266
}
267
}
268
269
IceBomba_HandlePlayerCollisions();
270
IceBomba_CheckOffScreen();
271
}
272
273
void IceBomba_State_FlyAway(void)
274
{
275
RSDK_THIS(IceBomba);
276
277
RSDK.ProcessAnimation(&self->wingAnimator);
278
279
if (self->direction) {
280
if (self->bodyAnimator.frameID < 4) {
281
++self->bodyAnimator.frameID;
282
++self->bombAnimator.frameID;
283
}
284
}
285
else {
286
if (self->bodyAnimator.frameID > 0) {
287
--self->bodyAnimator.frameID;
288
--self->bombAnimator.frameID;
289
}
290
}
291
292
self->position.x += self->velocity.x;
293
self->position.y -= 0x20000;
294
295
IceBomba_HandlePlayerCollisions();
296
IceBomba_CheckOffScreen();
297
}
298
299
void IceBomba_State_Bomb(void)
300
{
301
RSDK_THIS(IceBomba);
302
303
self->position.y += self->velocity.y;
304
self->velocity.y += 0x3800;
305
306
if (RSDK.CheckOnScreen(self, NULL)) {
307
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x100000, true)) {
308
RSDK.PlaySfx(IceBomba->sfxExplosion, false, 255);
309
CREATE_ENTITY(Explosion, INT_TO_VOID(EXPLOSION_ENEMY), self->position.x, self->position.y)->drawGroup = Zone->objectDrawGroup[1];
310
311
CREATE_ENTITY(Ice, INT_TO_VOID(ICE_CHILD_PILLAR), self->position.x, self->position.y + 0x100000);
312
RSDK.PlaySfx(IceBomba->sfxFreeze, false, 0xFF);
313
destroyEntity(self);
314
}
315
316
foreach_active(Player, player)
317
{
318
if (Player_CheckCollisionTouch(player, self, &IceBomba->hitboxBomb)) {
319
RSDK.PlaySfx(IceBomba->sfxExplosion, false, 0xFF);
320
CREATE_ENTITY(Explosion, INT_TO_VOID(EXPLOSION_ENEMY), self->position.x, self->position.y)->drawGroup = Zone->objectDrawGroup[1];
321
322
Ice_FreezePlayer(player);
323
destroyEntity(self);
324
foreach_break;
325
}
326
}
327
}
328
else {
329
destroyEntity(self);
330
}
331
}
332
333
#if GAME_INCLUDE_EDITOR
334
void IceBomba_EditorDraw(void)
335
{
336
RSDK_THIS(IceBomba);
337
338
self->drawFX |= FX_FLIP;
339
self->active = ACTIVE_BOUNDS;
340
self->alpha = 0x80;
341
self->startDist = self->dist;
342
self->updateRange.x = (self->dist + 0x80) << 16;
343
self->updateRange.y = ((self->dip << 7) + 0x8000) << 8;
344
345
RSDK.SetSpriteAnimation(IceBomba->aniFrames, 0, &self->bodyAnimator, true, 0);
346
RSDK.SetSpriteAnimation(IceBomba->aniFrames, 1, &self->wingAnimator, true, 0);
347
RSDK.SetSpriteAnimation(IceBomba->aniFrames, 2, &self->bombAnimator, true, 0);
348
349
self->direction = self->dir;
350
if (self->dir) {
351
self->bodyAnimator.frameID = 4;
352
self->bombAnimator.frameID = 4;
353
}
354
else {
355
self->bodyAnimator.frameID = 0;
356
self->bombAnimator.frameID = 0;
357
}
358
359
IceBomba_Draw();
360
}
361
362
void IceBomba_EditorLoad(void)
363
{
364
if (RSDK.CheckSceneFolder("PSZ1"))
365
IceBomba->aniFrames = RSDK.LoadSpriteAnimation("PSZ1/IceBomba.bin", SCOPE_STAGE);
366
else if (RSDK.CheckSceneFolder("PSZ2"))
367
IceBomba->aniFrames = RSDK.LoadSpriteAnimation("PSZ2/IceBomba.bin", SCOPE_STAGE);
368
369
RSDK_ACTIVE_VAR(IceBomba, dir);
370
RSDK_ENUM_VAR("Left", FLIP_NONE);
371
RSDK_ENUM_VAR("Right", FLIP_X);
372
}
373
#endif
374
375
void IceBomba_Serialize(void)
376
{
377
RSDK_EDITABLE_VAR(IceBomba, VAR_UINT8, dir);
378
RSDK_EDITABLE_VAR(IceBomba, VAR_UINT16, dist);
379
RSDK_EDITABLE_VAR(IceBomba, VAR_UINT16, dip);
380
}
381