Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/GHZ/Splats.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: Splats Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectSplats *Splats;
11
12
void Splats_Update(void)
13
{
14
RSDK_THIS(Splats);
15
StateMachine_Run(self->state);
16
}
17
18
void Splats_LateUpdate(void) {}
19
20
void Splats_StaticUpdate(void) {}
21
22
void Splats_Draw(void)
23
{
24
RSDK_THIS(Splats);
25
26
RSDK.DrawSprite(&self->splashAnimator, NULL, false);
27
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
28
}
29
30
void Splats_Create(void *data)
31
{
32
RSDK_THIS(Splats);
33
34
self->startPos = self->position;
35
self->startDir = self->direction;
36
self->visible = true;
37
self->active = ACTIVE_BOUNDS;
38
self->updateRange.x = 0x800000;
39
self->updateRange.y = 0x800000;
40
41
if (self->bounceCount < 1)
42
self->bounceCount = 1;
43
44
if (Splats->initialState == Splats_State_BounceAround) {
45
self->drawFX |= FX_FLIP;
46
self->drawGroup = Zone->objectDrawGroup[0];
47
RSDK.SetSpriteAnimation(Splats->aniFrames, 0, &self->mainAnimator, true, 0);
48
self->state = Splats_State_Init;
49
}
50
else {
51
switch (VOID_TO_INT(data)) {
52
case SPLATS_SPAWNER:
53
self->drawGroup = Zone->objectDrawGroup[1];
54
self->delay = 0;
55
RSDK.SetSpriteAnimation(Splats->aniFrames, 1, &self->mainAnimator, true, 0);
56
self->state = Splats_State_Init;
57
break;
58
59
case SPLATS_INKSPLATS:
60
self->drawFX |= FX_FLIP;
61
self->drawGroup = Zone->objectDrawGroup[0];
62
self->active = ACTIVE_NORMAL;
63
RSDK.SetSpriteAnimation(Splats->aniFrames, 0, &self->mainAnimator, true, 0);
64
self->mainAnimator.loopIndex = 1;
65
self->state = Splats_State_JumpOutOfJar;
66
self->mainAnimator.frameCount = 2;
67
break;
68
69
case SPLATS_SPLAT:
70
self->drawFX |= FX_FLIP;
71
self->inkEffect |= INK_ALPHA;
72
self->alpha = 256;
73
self->drawGroup = Zone->objectDrawGroup[1];
74
self->active = ACTIVE_NORMAL;
75
RSDK.SetSpriteAnimation(Splats->aniFrames, 3, &self->mainAnimator, true, 0);
76
self->state = Splats_State_InkSplat;
77
break;
78
}
79
}
80
}
81
82
void Splats_StageLoad(void)
83
{
84
if (RSDK.CheckSceneFolder("GHZ")) {
85
Splats->aniFrames = RSDK.LoadSpriteAnimation("GHZ/Splats.bin", SCOPE_STAGE);
86
87
Splats->initialState = Splats_State_BounceAround;
88
}
89
else if (RSDK.CheckSceneFolder("PSZ1")) {
90
Splats->aniFrames = RSDK.LoadSpriteAnimation("PSZ1/Splats.bin", SCOPE_STAGE);
91
92
Splats->initialState = Splats_State_InkJarSpawner;
93
}
94
95
Splats->hitboxBadnikGHZ.left = -10;
96
Splats->hitboxBadnikGHZ.top = -20;
97
Splats->hitboxBadnikGHZ.right = 6;
98
Splats->hitboxBadnikGHZ.bottom = 20;
99
100
Splats->hitboxJar.left = -18;
101
Splats->hitboxJar.top = -26;
102
Splats->hitboxJar.right = 18;
103
Splats->hitboxJar.bottom = 17;
104
105
Splats->hitboxBadnikPGZ.left = -18;
106
Splats->hitboxBadnikPGZ.top = -146;
107
Splats->hitboxBadnikPGZ.right = 18;
108
Splats->hitboxBadnikPGZ.bottom = -18;
109
110
DEBUGMODE_ADD_OBJ(Splats);
111
112
Splats->sfxSplatsSpawn = RSDK.GetSfx("PSZ/SplatsSpawn.wav");
113
Splats->sfxSplatsLand = RSDK.GetSfx("PSZ/SplatsLand.wav");
114
}
115
116
void Splats_DebugDraw(void)
117
{
118
if (Splats->initialState == Splats_State_BounceAround)
119
RSDK.SetSpriteAnimation(Splats->aniFrames, 0, &DebugMode->animator, true, 0);
120
else
121
RSDK.SetSpriteAnimation(Splats->aniFrames, 1, &DebugMode->animator, true, 0);
122
123
RSDK.DrawSprite(&DebugMode->animator, NULL, false);
124
}
125
126
void Splats_DebugSpawn(void)
127
{
128
RSDK_THIS(DebugMode);
129
CREATE_ENTITY(Splats, NULL, self->position.x, self->position.y);
130
}
131
132
void Splats_CheckPlayerCollisions(void)
133
{
134
RSDK_THIS(Splats);
135
136
foreach_active(Player, player)
137
{
138
if (Player_CheckBadnikTouch(player, self, &Splats->hitboxBadnikGHZ)) {
139
if (Splats->initialState == Splats_State_BounceAround) {
140
Player_CheckBadnikBreak(player, self, true);
141
}
142
else {
143
if (Player_CheckBadnikBreak(player, self, false)) {
144
EntitySplats *parent = self->parent;
145
if (parent) {
146
if (parent->classID == Splats->classID)
147
--parent->activeCount;
148
}
149
destroyEntity(self);
150
foreach_break;
151
}
152
}
153
}
154
}
155
}
156
157
void Splats_CheckOffScreen(void)
158
{
159
RSDK_THIS(Splats);
160
if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {
161
self->position = self->startPos;
162
self->direction = self->startDir;
163
self->isOnScreen = false;
164
Splats_Create(NULL);
165
}
166
}
167
168
void Splats_State_Init(void)
169
{
170
RSDK_THIS(Splats);
171
self->active = ACTIVE_NORMAL;
172
self->velocity.x = -0x10000;
173
174
self->state = Splats->initialState;
175
StateMachine_Run(self->state);
176
}
177
178
void Splats_State_BounceAround(void)
179
{
180
RSDK_THIS(Splats);
181
182
self->position.x += self->velocity.x;
183
self->position.y += self->velocity.y;
184
self->velocity.y += 0x3800;
185
186
if (self->velocity.y > 0 && RSDK.ObjectTileCollision(self, Zone->collisionLayers, 0, 0, 0, 0x100000, true)) {
187
if (self->bounceCount && ++self->activeCount >= self->bounceCount) {
188
self->activeCount = 0;
189
self->direction ^= FLIP_X;
190
self->velocity.x = -self->velocity.x;
191
}
192
self->position.y -= 0x80000;
193
self->velocity.y = -0x40000;
194
}
195
196
self->mainAnimator.frameID = self->velocity.y < 0;
197
198
Splats_CheckPlayerCollisions();
199
Splats_CheckOffScreen();
200
}
201
202
void Splats_State_SetupInkJar(void)
203
{
204
RSDK_THIS(Splats);
205
206
self->isOnScreen = false;
207
self->delay = 0;
208
self->active = ACTIVE_NORMAL;
209
210
self->state = Splats_State_InkJarSpawner;
211
Splats_State_InkJarSpawner();
212
}
213
214
void Splats_State_InkJarSpawner(void)
215
{
216
RSDK_THIS(Splats);
217
218
if (!self->isOnScreen) {
219
if (!self->onScreen)
220
return;
221
self->isOnScreen = true;
222
}
223
224
RSDK.ProcessAnimation(&self->splashAnimator);
225
226
bool32 disableSpawn = false;
227
foreach_active(Player, player)
228
{
229
Player_CheckCollisionBox(player, self, &Splats->hitboxJar);
230
disableSpawn |= Player_CheckCollisionTouch(player, self, &Splats->hitboxBadnikPGZ);
231
disableSpawn |= (player->animator.animationID == ANI_SPINDASH);
232
}
233
234
if (--self->delay <= 0) {
235
if (disableSpawn || (self->activeCount >= self->numActive)) {
236
self->delay++;
237
}
238
else {
239
RSDK.SetSpriteAnimation(Splats->aniFrames, 2, &self->splashAnimator, true, 0);
240
self->delay = self->minDelay;
241
RSDK.PlaySfx(Splats->sfxSplatsSpawn, false, 0xFF);
242
243
EntitySplats *splats = CREATE_ENTITY(Splats, INT_TO_VOID(SPLATS_INKSPLATS), self->position.x, self->position.y - 0x60000);
244
splats->parent = self;
245
splats->bounceCount = self->bounceCount;
246
splats->direction = self->direction;
247
splats->velocity.y = -0x60000;
248
if (self->direction == FLIP_NONE)
249
splats->velocity.x = -0x10000;
250
else
251
splats->velocity.x = 0x10000;
252
253
++self->activeCount;
254
}
255
}
256
257
if (!RSDK.CheckOnScreen(self, NULL)) {
258
self->state = Splats_State_SetupInkJar;
259
self->active = ACTIVE_NORMAL;
260
}
261
}
262
263
void Splats_State_JumpOutOfJar(void)
264
{
265
RSDK_THIS(Splats);
266
267
RSDK.ProcessAnimation(&self->mainAnimator);
268
269
self->position.y += self->velocity.y;
270
self->velocity.y += 0x3800;
271
272
if (self->velocity.y > -0x40000)
273
self->position.x += self->velocity.x;
274
275
if (self->velocity.y > 0) {
276
self->mainAnimator.loopIndex = 4;
277
self->mainAnimator.frameCount = 5;
278
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, 0, 0, 0, 0x120000, true)) {
279
RSDK.PlaySfx(Splats->sfxSplatsLand, false, 255);
280
EntitySplats *splat = CREATE_ENTITY(Splats, INT_TO_VOID(SPLATS_SPLAT), self->position.x, self->position.y);
281
splat->direction = self->direction;
282
self->delay = 4;
283
self->state = Splats_State_HandleLanding;
284
}
285
}
286
Splats_CheckPlayerCollisions();
287
}
288
289
void Splats_State_HandleBouncing(void)
290
{
291
RSDK_THIS(Splats);
292
293
RSDK.ProcessAnimation(&self->mainAnimator);
294
self->position.x += self->velocity.x;
295
self->position.y += self->velocity.y;
296
self->velocity.y += 0x3800;
297
298
if (self->velocity.y > 0) {
299
self->mainAnimator.loopIndex = 4;
300
self->mainAnimator.frameCount = 5;
301
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, 0, 0, 0, 0x120000, true)) {
302
RSDK.PlaySfx(Splats->sfxSplatsLand, false, 0xFF);
303
if (self->bounceCount) {
304
if (++self->activeCount < self->bounceCount) {
305
self->delay = 4;
306
self->state = Splats_State_HandleLanding;
307
}
308
else {
309
RSDK.SetSpriteAnimation(Splats->aniFrames, 4, &self->mainAnimator, true, 0);
310
self->state = Splats_State_NoMoreJumps;
311
self->activeCount = 0;
312
}
313
}
314
315
EntitySplats *splat = CREATE_ENTITY(Splats, INT_TO_VOID(SPLATS_SPLAT), self->position.x, self->position.y);
316
splat->direction = self->direction;
317
}
318
}
319
320
if (RSDK.CheckOnScreen(self, NULL)) {
321
Splats_CheckPlayerCollisions();
322
}
323
else {
324
EntitySplats *parent = self->parent;
325
if (parent && parent->classID == Splats->classID)
326
--parent->activeCount;
327
328
destroyEntity(self);
329
}
330
}
331
332
void Splats_State_HandleLanding(void)
333
{
334
RSDK_THIS(Splats);
335
336
if (--self->delay <= 0) {
337
RSDK.SetSpriteAnimation(Splats->aniFrames, 0, &self->mainAnimator, true, 0);
338
self->mainAnimator.loopIndex = 1;
339
self->mainAnimator.frameCount = 2;
340
self->position.y -= 0x80000;
341
self->velocity.y = -0x40000;
342
self->state = Splats_State_HandleBouncing;
343
}
344
345
if (RSDK.CheckOnScreen(self, NULL)) {
346
Splats_CheckPlayerCollisions();
347
}
348
else {
349
EntitySplats *parent = self->parent;
350
if (parent && parent->classID == Splats->classID)
351
--parent->activeCount;
352
353
destroyEntity(self);
354
}
355
}
356
357
void Splats_State_NoMoreJumps(void)
358
{
359
RSDK_THIS(Splats);
360
361
RSDK.ProcessAnimation(&self->mainAnimator);
362
363
if (self->mainAnimator.frameID == self->mainAnimator.frameCount - 1) {
364
RSDK.SetSpriteAnimation(Splats->aniFrames, 0, &self->mainAnimator, true, 0);
365
self->position.y -= 0x80000;
366
self->mainAnimator.frameCount = 2;
367
self->mainAnimator.loopIndex = 1;
368
self->direction ^= FLIP_X;
369
self->velocity.y = -0x40000;
370
self->velocity.x = -self->velocity.x;
371
self->state = Splats_State_HandleBouncing;
372
}
373
374
if (RSDK.CheckOnScreen(self, NULL)) {
375
Splats_CheckPlayerCollisions();
376
}
377
else {
378
EntitySplats *parent = self->parent;
379
if (parent && parent->classID == Splats->classID)
380
--parent->activeCount;
381
382
destroyEntity(self);
383
}
384
}
385
386
void Splats_State_InkSplat(void)
387
{
388
RSDK_THIS(Splats);
389
RSDK.ProcessAnimation(&self->mainAnimator);
390
391
if (self->delay >= 30) {
392
self->alpha -= 2;
393
if (!self->alpha)
394
destroyEntity(self);
395
}
396
else {
397
self->delay++;
398
}
399
}
400
401
#if GAME_INCLUDE_EDITOR
402
void Splats_EditorDraw(void)
403
{
404
RSDK_THIS(Splats);
405
406
if (RSDK.CheckSceneFolder("GHZ")) {
407
self->drawFX |= FX_FLIP;
408
self->drawGroup = Zone->objectDrawGroup[0];
409
RSDK.SetSpriteAnimation(Splats->aniFrames, 0, &self->mainAnimator, true, 0);
410
}
411
else {
412
self->drawFX = FX_NONE;
413
self->drawGroup = Zone->objectDrawGroup[1];
414
RSDK.SetSpriteAnimation(Splats->aniFrames, 1, &self->mainAnimator, true, 0);
415
}
416
417
Splats_Draw();
418
}
419
420
void Splats_EditorLoad(void)
421
{
422
if (RSDK.CheckSceneFolder("GHZ"))
423
Splats->aniFrames = RSDK.LoadSpriteAnimation("GHZ/Splats.bin", SCOPE_STAGE);
424
else if (RSDK.CheckSceneFolder("PSZ1"))
425
Splats->aniFrames = RSDK.LoadSpriteAnimation("PSZ1/Splats.bin", SCOPE_STAGE);
426
427
RSDK_ACTIVE_VAR(Splats, direction);
428
RSDK_ENUM_VAR("Left", FLIP_NONE);
429
RSDK_ENUM_VAR("Right", FLIP_X);
430
}
431
#endif
432
433
void Splats_Serialize(void)
434
{
435
RSDK_EDITABLE_VAR(Splats, VAR_UINT8, bounceCount);
436
RSDK_EDITABLE_VAR(Splats, VAR_UINT8, direction);
437
RSDK_EDITABLE_VAR(Splats, VAR_UINT8, numActive);
438
RSDK_EDITABLE_VAR(Splats, VAR_UINT16, minDelay);
439
}
440
441