Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/TMZ/FlasherMKII.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: FlasherMKII Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectFlasherMKII *FlasherMKII;
11
12
void FlasherMKII_Update(void)
13
{
14
RSDK_THIS(FlasherMKII);
15
16
RSDK.ProcessAnimation(&self->animator);
17
18
StateMachine_Run(self->state);
19
}
20
21
void FlasherMKII_LateUpdate(void) {}
22
23
void FlasherMKII_StaticUpdate(void) {}
24
25
void FlasherMKII_Draw(void)
26
{
27
RSDK_THIS(FlasherMKII);
28
29
RSDK.DrawSprite(&self->animator, NULL, false);
30
}
31
32
void FlasherMKII_Create(void *data)
33
{
34
RSDK_THIS(FlasherMKII);
35
36
self->drawFX |= FX_FLIP;
37
if (!SceneInfo->inEditor) {
38
self->active = ACTIVE_BOUNDS;
39
self->updateRange.x = 0x800000;
40
self->updateRange.y = 0x800000;
41
self->visible = true;
42
self->drawGroup = Zone->objectDrawGroup[0];
43
self->startPos = self->position;
44
45
switch (self->orientation) {
46
case FLASHERMKII_ORIENTATION_UP:
47
self->type = 0;
48
self->direction = FLIP_NONE;
49
break;
50
51
case FLASHERMKII_ORIENTATION_DOWN:
52
self->type = 0;
53
self->direction = FLIP_Y;
54
break;
55
56
case FLASHERMKII_ORIENTATION_RIGHT:
57
self->direction = FLIP_NONE;
58
self->type = 4;
59
break;
60
61
case FLASHERMKII_ORIENTATION_LEFT:
62
self->direction = FLIP_X;
63
self->type = 4;
64
break;
65
66
default: break;
67
}
68
69
RSDK.SetSpriteAnimation(FlasherMKII->aniFrames, self->type, &self->animator, true, 0);
70
self->state = FlasherMKII_State_Idle;
71
}
72
}
73
74
void FlasherMKII_StageLoad(void)
75
{
76
if (RSDK.CheckSceneFolder("TMZ1") || RSDK.CheckSceneFolder("TMZ2"))
77
FlasherMKII->aniFrames = RSDK.LoadSpriteAnimation("TMZ1/FlasherMKII.bin", SCOPE_STAGE);
78
79
DEBUGMODE_ADD_OBJ(FlasherMKII);
80
81
FlasherMKII->sfxFlop = RSDK.GetSfx("TMZ1/FlasherFlop.wav");
82
FlasherMKII->sfxZap = RSDK.GetSfx("TMZ1/FlasherZap.wav");
83
}
84
85
void FlasherMKII_DebugSpawn(void)
86
{
87
RSDK_THIS(FlasherMKII);
88
89
CREATE_ENTITY(FlasherMKII, NULL, self->position.x, self->position.y);
90
}
91
92
void FlasherMKII_DebugDraw(void)
93
{
94
RSDK.SetSpriteAnimation(FlasherMKII->aniFrames, 0, &DebugMode->animator, true, 0);
95
RSDK.DrawSprite(&DebugMode->animator, NULL, false);
96
}
97
98
void FlasherMKII_CheckOffScreen(void)
99
{
100
RSDK_THIS(FlasherMKII);
101
102
if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange))
103
FlasherMKII_Create(NULL);
104
}
105
106
void FlasherMKII_HandlePlayerCollisions(void)
107
{
108
RSDK_THIS(FlasherMKII);
109
110
foreach_active(Player, player)
111
{
112
Hitbox *hitbox = RSDK.GetHitbox(&self->animator, 0);
113
114
if (Player_CheckBadnikTouch(player, self, hitbox)) {
115
if ((self->animator.animationID & 3) == 3) {
116
if (player->shield == SHIELD_LIGHTNING || player->invincibleTimer || player->blinkTimer) {
117
if (Player_CheckBadnikBreak(player, self, true))
118
RSDK.StopSfx(FlasherMKII->sfxZap);
119
}
120
else {
121
Player_Hurt(player, self);
122
}
123
}
124
else {
125
Player_CheckBadnikBreak(player, self, true);
126
}
127
}
128
}
129
}
130
131
void FlasherMKII_HandleHarmPlayerCollisions(void)
132
{
133
RSDK_THIS(FlasherMKII);
134
135
foreach_active(Player, player)
136
{
137
if (player->shield == SHIELD_LIGHTNING || player->invincibleTimer || player->blinkTimer) {
138
Hitbox *hitbox = RSDK.GetHitbox(&self->animator, 0);
139
if (Player_CheckBadnikTouch(player, self, hitbox) && Player_CheckBadnikBreak(player, self, true))
140
RSDK.StopSfx(FlasherMKII->sfxZap);
141
}
142
else {
143
Hitbox *hitbox = RSDK.GetHitbox(&self->animator, 1);
144
if (Player_CheckCollisionTouch(player, self, hitbox))
145
Player_Hurt(player, self);
146
}
147
}
148
}
149
150
void FlasherMKII_State_Idle(void)
151
{
152
RSDK_THIS(FlasherMKII);
153
154
self->active = ACTIVE_NORMAL;
155
if (self->timer > 0)
156
self->timer--;
157
158
EntityPlayer *player = Player_GetNearestPlayer();
159
if (player) {
160
int32 rx = (self->position.x - player->position.x) >> 16;
161
int32 ry = (self->position.y - player->position.y) >> 16;
162
163
if (!self->timer && rx * rx + ry * ry < 0x1000) {
164
RSDK.SetSpriteAnimation(FlasherMKII->aniFrames, self->type + 2, &self->animator, false, 0);
165
RSDK.PlaySfx(FlasherMKII->sfxZap, false, 255);
166
self->state = FlasherMKII_State_WeakFlash;
167
}
168
else {
169
switch (self->orientation) {
170
case FLASHERMKII_ORIENTATION_UP:
171
if (player->position.x >= self->position.x) {
172
if ((uint32)(rx + 0xFF) <= 0xBE && RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0x600000, 0xC0000, 2)) {
173
RSDK.SetSpriteAnimation(FlasherMKII->aniFrames, self->type + 1, &self->animator, false, 0);
174
self->direction = FLIP_X;
175
self->velocity.x = 0x220000;
176
self->state = FlasherMKII_State_Moving;
177
break;
178
}
179
}
180
else if ((uint32)(rx - 65) <= 0xBE && RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, -0x600000, 0xC0000, 2)) {
181
RSDK.SetSpriteAnimation(FlasherMKII->aniFrames, self->type + 1, &self->animator, false, 0);
182
self->direction = FLIP_NONE;
183
self->velocity.x = -0x220000;
184
self->state = FlasherMKII_State_Moving;
185
break;
186
}
187
break;
188
189
case FLASHERMKII_ORIENTATION_DOWN:
190
if (player->position.x >= self->position.x) {
191
if ((uint32)(rx + 0xFF) <= 0xBE && RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_ROOF, 0, 0x600000, -0xC0000, 2)) {
192
RSDK.SetSpriteAnimation(FlasherMKII->aniFrames, self->type + 1, &self->animator, false, 0);
193
self->velocity.x = 0x220000;
194
self->direction = FLIP_XY;
195
self->state = FlasherMKII_State_Moving;
196
break;
197
}
198
}
199
else if ((uint32)(rx - 65) <= 0xBE && RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_ROOF, 0, -0x600000, -0xC0000, 2)) {
200
RSDK.SetSpriteAnimation(FlasherMKII->aniFrames, self->type + 1, &self->animator, false, 0);
201
self->direction = FLIP_Y;
202
self->velocity.x = -0x220000;
203
self->state = FlasherMKII_State_Moving;
204
break;
205
}
206
break;
207
208
case FLASHERMKII_ORIENTATION_RIGHT:
209
if (player->position.y >= self->position.y) {
210
if ((uint32)(ry + 0xFF) <= 0xBE && RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_RWALL, 0, -0xC0000, 0x600000, 2)) {
211
RSDK.SetSpriteAnimation(FlasherMKII->aniFrames, self->type + 1, &self->animator, false, 0);
212
self->direction = FLIP_Y;
213
self->velocity.y = 0x220000;
214
self->state = FlasherMKII_State_Moving;
215
break;
216
}
217
}
218
else if ((uint32)(ry - 65) <= 0xBE && RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_RWALL, 0, -0xC0000, -0x600000, 2)) {
219
RSDK.SetSpriteAnimation(FlasherMKII->aniFrames, self->type + 1, &self->animator, false, 0);
220
self->direction = FLIP_NONE;
221
self->velocity.y = -0x220000;
222
self->state = FlasherMKII_State_Moving;
223
break;
224
}
225
break;
226
227
case FLASHERMKII_ORIENTATION_LEFT:
228
if (player->position.y >= self->position.y) {
229
if ((uint32)(ry + 0xFF) <= 0xBE && RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_LWALL, 0, 0xC0000, 0x600000, 2)) {
230
RSDK.SetSpriteAnimation(FlasherMKII->aniFrames, self->type + 1, &self->animator, false, 0);
231
self->velocity.y = 0x220000;
232
self->direction = FLIP_XY;
233
self->state = FlasherMKII_State_Moving;
234
break;
235
}
236
}
237
else if ((uint32)(ry - 65) <= 0xBE && RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_LWALL, 0, 0xC0000, -0x600000, 2)) {
238
RSDK.SetSpriteAnimation(FlasherMKII->aniFrames, self->type + 1, &self->animator, false, 0);
239
self->direction = FLIP_X;
240
self->velocity.y = -0x220000;
241
self->state = FlasherMKII_State_Moving;
242
break;
243
}
244
break;
245
246
default: break;
247
}
248
}
249
}
250
251
FlasherMKII_HandlePlayerCollisions();
252
FlasherMKII_CheckOffScreen();
253
}
254
255
void FlasherMKII_State_Moving(void)
256
{
257
RSDK_THIS(FlasherMKII);
258
259
if ((self->animator.frameID == 5 || self->animator.frameID == 12) && self->animator.timer == 1) {
260
self->position.x += self->velocity.x;
261
self->position.y += self->velocity.y;
262
263
if (self->onScreen == 1)
264
RSDK.PlaySfx(FlasherMKII->sfxFlop, false, 255);
265
}
266
267
if (self->animator.frameID == self->animator.frameCount - 1) {
268
RSDK.SetSpriteAnimation(FlasherMKII->aniFrames, self->type, &self->animator, false, 0);
269
self->state = FlasherMKII_State_Idle;
270
}
271
272
FlasherMKII_HandlePlayerCollisions();
273
FlasherMKII_CheckOffScreen();
274
}
275
276
void FlasherMKII_State_WeakFlash(void)
277
{
278
RSDK_THIS(FlasherMKII);
279
280
if (++self->timer == 60) {
281
self->timer = 0;
282
RSDK.SetSpriteAnimation(FlasherMKII->aniFrames, self->type + 3, &self->animator, false, 0);
283
self->state = FlasherMKII_State_StrongFlash;
284
}
285
286
FlasherMKII_HandlePlayerCollisions();
287
FlasherMKII_CheckOffScreen();
288
}
289
290
void FlasherMKII_State_StrongFlash(void)
291
{
292
RSDK_THIS(FlasherMKII);
293
294
if (++self->timer == 120) {
295
self->timer = 0;
296
RSDK.SetSpriteAnimation(FlasherMKII->aniFrames, self->type + 2, &self->animator, false, 0);
297
self->state = FlasherMKII_State_FinishedFlashing;
298
}
299
300
FlasherMKII_HandleHarmPlayerCollisions();
301
FlasherMKII_CheckOffScreen();
302
}
303
304
void FlasherMKII_State_FinishedFlashing(void)
305
{
306
RSDK_THIS(FlasherMKII);
307
308
if (++self->timer == 30) {
309
RSDK.SetSpriteAnimation(FlasherMKII->aniFrames, self->type, &self->animator, false, 0);
310
self->state = FlasherMKII_State_Idle;
311
}
312
313
FlasherMKII_HandlePlayerCollisions();
314
FlasherMKII_CheckOffScreen();
315
}
316
317
#if GAME_INCLUDE_EDITOR
318
void FlasherMKII_EditorDraw(void)
319
{
320
RSDK_THIS(FlasherMKII);
321
322
self->startPos = self->position;
323
324
switch (self->orientation) {
325
case FLASHERMKII_ORIENTATION_UP:
326
self->type = 0;
327
self->direction = FLIP_NONE;
328
break;
329
330
case FLASHERMKII_ORIENTATION_DOWN:
331
self->type = 0;
332
self->direction = FLIP_Y;
333
break;
334
335
case FLASHERMKII_ORIENTATION_RIGHT:
336
self->direction = FLIP_NONE;
337
self->type = 4;
338
break;
339
340
case FLASHERMKII_ORIENTATION_LEFT:
341
self->direction = FLIP_X;
342
self->type = 4;
343
break;
344
345
default: break;
346
}
347
348
RSDK.SetSpriteAnimation(FlasherMKII->aniFrames, self->type, &self->animator, true, 0);
349
350
FlasherMKII_Draw();
351
}
352
353
void FlasherMKII_EditorLoad(void)
354
{
355
FlasherMKII->aniFrames = RSDK.LoadSpriteAnimation("TMZ1/FlasherMKII.bin", SCOPE_STAGE);
356
357
RSDK_ACTIVE_VAR(FlasherMKII, orientation);
358
RSDK_ENUM_VAR("Up", FLASHERMKII_ORIENTATION_UP);
359
RSDK_ENUM_VAR("Down", FLASHERMKII_ORIENTATION_DOWN);
360
RSDK_ENUM_VAR("Right", FLASHERMKII_ORIENTATION_RIGHT);
361
RSDK_ENUM_VAR("Left", FLASHERMKII_ORIENTATION_LEFT);
362
}
363
#endif
364
365
void FlasherMKII_Serialize(void) { RSDK_EDITABLE_VAR(FlasherMKII, VAR_UINT8, orientation); }
366
367