Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/LRZ/KingAttack.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: KingAttack Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectKingAttack *KingAttack;
11
12
void KingAttack_Update(void)
13
{
14
RSDK_THIS(KingAttack);
15
16
StateMachine_Run(self->state);
17
}
18
19
void KingAttack_LateUpdate(void) {}
20
21
void KingAttack_StaticUpdate(void) {}
22
23
void KingAttack_Draw(void)
24
{
25
RSDK_THIS(KingAttack);
26
27
int32 x = ScreenInfo->position.x << 16;
28
int32 y = ScreenInfo->position.y << 16;
29
30
switch (self->type) {
31
case KINGATTACK_LASER:
32
for (int32 i = 0; i < 6; i += 2) {
33
Vector2 vertices[4];
34
color colors[4];
35
36
vertices[0].x = self->laserVertPostions[i].x - x;
37
vertices[0].y = self->laserVertPostions[i].y - y;
38
colors[0] = self->laserColors[i];
39
40
vertices[1].x = self->laserVertPostions[i + 1].x - x;
41
vertices[1].y = self->laserVertPostions[i + 1].y - y;
42
colors[1] = self->laserColors[i + 1];
43
44
vertices[2].x = self->laserVertPostions[i + 3].x - x;
45
vertices[2].y = self->laserVertPostions[i + 3].y - y;
46
colors[2] = self->laserColors[i + 3];
47
48
vertices[3].x = self->laserVertPostions[i + 2].x - x;
49
vertices[3].y = self->laserVertPostions[i + 2].y - y;
50
colors[3] = self->laserColors[i + 2];
51
52
RSDK.DrawBlendedFace(vertices, colors, 4, self->alpha, INK_ADD);
53
}
54
//[Fallthrough]
55
default: RSDK.DrawSprite(&self->animator, NULL, false); break;
56
57
case KINGATTACK_ENERGYLINE:
58
RSDK.DrawLine(self->position.x, self->position.y, self->targetPos.x, self->targetPos.y, 0x0080F0, self->alpha, INK_ADD, false);
59
break;
60
}
61
}
62
63
void KingAttack_Create(void *data)
64
{
65
RSDK_THIS(KingAttack);
66
67
if (!SceneInfo->inEditor) {
68
self->drawGroup = Zone->objectDrawGroup[1];
69
self->active = ACTIVE_NORMAL;
70
self->updateRange.x = 0x800000;
71
self->updateRange.y = 0x800000;
72
self->type = VOID_TO_INT(data);
73
74
switch (self->type) {
75
case KINGATTACK_LASER:
76
self->inkEffect = INK_ADD;
77
self->visible = true;
78
self->laserColors = KingAttack->laserColors;
79
self->state = KingAttack_State_Laser;
80
81
KingAttack->laserEruptActive = false;
82
83
RSDK.PlaySfx(KingAttack->sfxLaserSweep, false, 255);
84
RSDK.SetSpriteAnimation(KingAttack->aniFrames, 21, &self->animator, true, 0);
85
break;
86
87
case KINGATTACK_LASERBLAST:
88
RSDK.SetSpriteAnimation(KingAttack->aniFrames, 23, &self->animator, true, 0);
89
self->state = KingAttack_State_LaserBlast_Delay;
90
self->drawFX = FX_FLIP;
91
92
self->hitbox.left = -16;
93
self->hitbox.top = -64;
94
self->hitbox.right = 16;
95
self->hitbox.bottom = 0;
96
break;
97
98
case KINGATTACK_ORBIT:
99
self->drawFX = FX_SCALE;
100
self->visible = true;
101
RSDK.SetSpriteAnimation(KingAttack->aniFrames, 20, &self->animator, true, RSDK.Rand(0, 6));
102
103
self->state = KingAttack_State_OrbitAppear;
104
105
self->hitbox.left = -10;
106
self->hitbox.top = -10;
107
self->hitbox.right = 10;
108
self->hitbox.bottom = 10;
109
break;
110
111
case KINGATTACK_TRAIL:
112
self->drawGroup = Zone->objectDrawGroup[0];
113
self->inkEffect = INK_ADD;
114
self->visible = true;
115
self->alpha = 0xC0;
116
RSDK.SetSpriteAnimation(KingAttack->aniFrames, 24, &self->animator, true, 0);
117
118
self->state = KingAttack_State_Trail;
119
break;
120
121
case KINGATTACK_LARGEBULLET:
122
self->drawFX = FX_SCALE;
123
self->visible = true;
124
125
RSDK.SetSpriteAnimation(KingAttack->aniFrames, 20, &self->animator, true, RSDK.Rand(0, 6));
126
127
self->scale.x = 0x100;
128
self->scale.y = 0x100;
129
self->state = KingAttack_State_LargeBullet_Appear;
130
break;
131
132
case KINGATTACK_ENERGYLINE:
133
self->drawGroup = Zone->objectDrawGroup[0];
134
self->visible = true;
135
136
self->state = KingAttack_State_EnergyLine;
137
138
self->angle = RSDK.Rand(0, 256);
139
self->timer = 0x4000;
140
self->alpha = 0x100;
141
break;
142
143
case KINGATTACK_SMALLBULLET:
144
self->drawGroup = Zone->objectDrawGroup[0];
145
self->drawFX = FX_ROTATE;
146
self->visible = true;
147
148
RSDK.SetSpriteAnimation(KingAttack->aniFrames, 21, &self->animator, true, 0);
149
self->state = KingAttack_State_SmallBullet;
150
151
self->hitbox.left = -4;
152
self->hitbox.top = -4;
153
self->hitbox.right = 4;
154
self->hitbox.bottom = 4;
155
break;
156
157
default: break;
158
}
159
}
160
}
161
162
void KingAttack_StageLoad(void)
163
{
164
KingAttack->aniFrames = RSDK.LoadSpriteAnimation("LRZ3/HeavyKing.bin", SCOPE_STAGE);
165
166
KingAttack->sfxLaserSweep = RSDK.GetSfx("LRZ/LaserSweep.wav");
167
KingAttack->sfxLaserErupt = RSDK.GetSfx("LRZ/LaserErupt.wav");
168
169
KingAttack->laserEruptActive = false;
170
171
KingAttack->sfxElecPulse = RSDK.GetSfx("Stage/ElecPulse.wav");
172
KingAttack->sfxTwinShot = RSDK.GetSfx("LRZ/TwinShot.wav");
173
174
int32 sfxID = Soundboard_LoadSfx("LRZ/ElecIdle.wav", true, KingAttack_SfxCheck_ElecIdle, StateMachine_None);
175
if (sfxID >= 0)
176
Soundboard->sfxFadeOutDuration[sfxID] = 30;
177
}
178
179
bool32 KingAttack_SfxCheck_ElecIdle(void)
180
{
181
int32 count = 0;
182
183
foreach_active(KingAttack, attack)
184
{
185
if (attack->type == KINGATTACK_ORBIT)
186
count++;
187
}
188
189
return count > 0;
190
}
191
192
void KingAttack_CheckPlayerCollisions(void)
193
{
194
RSDK_THIS(KingAttack);
195
196
foreach_active(Player, player)
197
{
198
if (Player_CheckCollisionTouch(player, self, &self->hitbox)) {
199
Player_Hurt(player, self);
200
}
201
}
202
}
203
204
void KingAttack_HandleLaserPositions(void)
205
{
206
RSDK_THIS(KingAttack);
207
208
EntityHeavyKing *king = (EntityHeavyKing *)self->parent;
209
210
int32 x = 0;
211
if (king->direction)
212
x = king->position.x - 0x240000;
213
else
214
x = king->position.x + 0x240000;
215
int32 y = king->position.y - 0x300000;
216
217
self->laserVertPostions[0].x = x - 0x40000;
218
self->laserVertPostions[1].x = self->position.x - 0x40000;
219
self->laserVertPostions[2].x = x - 0x20000;
220
self->laserVertPostions[3].x = self->position.x - 0x20000;
221
self->laserVertPostions[4].x = x + 0x20000;
222
self->laserVertPostions[5].x = self->position.x + 0x20000;
223
self->laserVertPostions[6].x = x + 0x40000;
224
self->laserVertPostions[7].x = self->position.x + 0x40000;
225
226
self->laserVertPostions[0].y = y;
227
self->laserVertPostions[1].y = HeavyKing->spinRaySpawnPos;
228
self->laserVertPostions[2].y = y;
229
self->laserVertPostions[3].y = HeavyKing->spinRaySpawnPos;
230
self->laserVertPostions[4].y = y;
231
self->laserVertPostions[5].y = HeavyKing->spinRaySpawnPos;
232
self->laserVertPostions[6].y = y;
233
self->laserVertPostions[7].y = HeavyKing->spinRaySpawnPos;
234
}
235
236
void KingAttack_State_Laser(void)
237
{
238
RSDK_THIS(KingAttack);
239
240
RSDK.ProcessAnimation(&self->animator);
241
242
self->position.x += self->velocity.x;
243
++self->timer;
244
245
KingAttack_HandleLaserPositions();
246
247
if (self->timer < 16) {
248
if (self->alpha < 0xC0)
249
self->alpha += 0x10;
250
}
251
else if (self->timer > 48) {
252
if (self->alpha > 0)
253
self->alpha -= 0x10;
254
}
255
256
if (!(self->timer & 3)) {
257
EntityKingAttack *attack = CREATE_ENTITY(KingAttack, INT_TO_VOID(KINGATTACK_LASERBLAST), self->position.x, self->position.y);
258
attack->direction = (self->timer >> 3) & 1;
259
}
260
261
if (self->timer == 64)
262
destroyEntity(self);
263
}
264
265
void KingAttack_State_LaserBlast_Delay(void)
266
{
267
RSDK_THIS(KingAttack);
268
269
if (++self->timer == 30) {
270
self->timer = 0;
271
self->visible = true;
272
273
if (KingAttack->laserEruptActive) {
274
KingAttack->laserEruptActive = false;
275
}
276
else {
277
Camera_ShakeScreen(0, 0, 5);
278
RSDK.PlaySfx(KingAttack->sfxLaserErupt, false, 255);
279
KingAttack->laserEruptActive = true;
280
}
281
282
self->state = KingAttack_State_LaserBlast_Erupt;
283
}
284
}
285
286
void KingAttack_State_LaserBlast_Erupt(void)
287
{
288
RSDK_THIS(KingAttack);
289
290
RSDK.ProcessAnimation(&self->animator);
291
292
if (self->animator.frameID > 8 && self->animator.frameID < 16)
293
KingAttack_CheckPlayerCollisions();
294
295
if (self->animator.frameID == self->animator.frameCount - 1)
296
destroyEntity(self);
297
}
298
299
void KingAttack_State_OrbitAppear(void)
300
{
301
RSDK_THIS(KingAttack);
302
303
EntityHeavyKing *king = (EntityHeavyKing *)self->parent;
304
305
RSDK.ProcessAnimation(&self->animator);
306
307
self->angle = (self->angle + 12) & 0x3FF;
308
if (self->scale.x < 512) {
309
self->scale.x += 0x20;
310
self->scale.y = self->scale.x;
311
}
312
313
self->velocity.x = self->position.x;
314
self->velocity.y = self->position.y;
315
316
int32 x = 0;
317
if (king->direction)
318
x = RSDK.Cos1024(self->angle) - 0x240;
319
else
320
x = RSDK.Cos1024(self->angle) + 0x240;
321
322
self->position.x = (x << 12) + king->position.x;
323
self->position.y = (((RSDK.Sin1024(self->angle) - 0x300) << 12) + king->position.y);
324
325
self->velocity.x = self->position.x - self->velocity.x;
326
self->velocity.y = self->position.y - self->velocity.y;
327
328
KingAttack_CheckPlayerCollisions();
329
330
if (++self->timer == 120) {
331
self->timer = 0;
332
self->targetPos = king->position;
333
self->state = KingAttack_State_Orbiting;
334
}
335
}
336
337
void KingAttack_State_Orbiting(void)
338
{
339
RSDK_THIS(KingAttack);
340
341
EntityHeavyKing *king = (EntityHeavyKing *)self->parent;
342
343
RSDK.ProcessAnimation(&self->animator);
344
345
self->position.x += king->position.x - self->targetPos.x;
346
self->position.y += king->position.y - self->targetPos.y;
347
348
if (self->position.x <= king->position.x) {
349
if (self->position.x < king->position.x)
350
self->velocity.x += 0x4000;
351
}
352
else {
353
self->velocity.x -= 0x4000;
354
}
355
356
if (self->position.y <= king->position.y) {
357
if (self->position.y < king->position.y)
358
self->velocity.y += 0x3800;
359
}
360
else {
361
self->velocity.y -= 0x3800;
362
}
363
364
if (self->velocity.x >= -0x50000) {
365
if (self->velocity.x > 0x50000)
366
self->velocity.x = 0x50000;
367
}
368
else {
369
self->velocity.x = -0x50000;
370
}
371
372
if (self->velocity.y >= -0x50000) {
373
if (self->velocity.y > 0x50000)
374
self->velocity.y = 0x50000;
375
}
376
else {
377
self->velocity.y = -0x50000;
378
}
379
380
self->position.x += self->velocity.x;
381
self->position.y += self->velocity.y;
382
383
self->targetPos = king->position;
384
385
self->angle = (self->angle + 12) & 0x3FF;
386
387
self->scale.x += (0x180 - self->scale.x - (RSDK.Sin1024(self->angle) >> 3)) >> 3;
388
self->scale.y = self->scale.x;
389
390
KingAttack_CheckPlayerCollisions();
391
392
if (self->angle < 512)
393
self->drawGroup = Zone->objectDrawGroup[0] - 1;
394
else
395
self->drawGroup = Zone->objectDrawGroup[0];
396
}
397
398
void KingAttack_State_OrbitLaunched(void)
399
{
400
RSDK_THIS(KingAttack);
401
402
RSDK.ProcessAnimation(&self->animator);
403
404
++self->timer;
405
if (!(self->timer & 3))
406
CREATE_ENTITY(KingAttack, INT_TO_VOID(KINGATTACK_TRAIL), self->position.x, self->position.y);
407
408
if (self->scale.x < 512) {
409
self->scale.x += 0x20;
410
self->scale.y = self->scale.x;
411
}
412
413
self->velocity.x += ((self->targetVelocity.x - self->velocity.x) >> 3);
414
self->velocity.y += ((self->targetVelocity.y - self->velocity.y) >> 3);
415
416
self->position.x += self->velocity.x;
417
self->position.y += self->velocity.y;
418
419
KingAttack_CheckPlayerCollisions();
420
421
if (!RSDK.CheckOnScreen(self, NULL))
422
destroyEntity(self);
423
}
424
425
void KingAttack_State_Trail(void)
426
{
427
RSDK_THIS(KingAttack);
428
429
if (self->timer++ >= 8) {
430
self->alpha -= 8;
431
432
if (self->alpha <= 0)
433
destroyEntity(self);
434
}
435
}
436
437
void KingAttack_State_LargeBullet_Appear(void)
438
{
439
RSDK_THIS(KingAttack);
440
441
EntityHeavyKing *king = (EntityHeavyKing *)self->parent;
442
443
RSDK.ProcessAnimation(&self->animator);
444
445
if (self->scale.x < 0x400)
446
self->scale.x += 4;
447
448
self->scale.y = self->scale.x;
449
450
++self->timer;
451
452
self->position = king->position;
453
if (king->direction)
454
self->position.x -= 0x240000;
455
else
456
self->position.x += 0x240000;
457
self->position.y -= 0x300000;
458
459
if (!(self->timer & 3)) {
460
EntityKingAttack *attack = CREATE_ENTITY(KingAttack, INT_TO_VOID(KINGATTACK_ENERGYLINE), self->position.x, self->position.y);
461
attack->parent = (Entity *)self;
462
}
463
464
if (self->timer == 120) {
465
self->timer = 0;
466
self->state = KingAttack_State_LargeBullet_TwinShot;
467
}
468
}
469
470
void KingAttack_State_EnergyLine(void)
471
{
472
RSDK_THIS(KingAttack);
473
474
EntityKingAttack *parent = (EntityKingAttack *)self->parent;
475
476
self->position.x = self->timer * RSDK.Cos256(self->angle);
477
self->position.y = self->timer * RSDK.Sin256(self->angle);
478
479
self->targetPos.x = self->position.x - (self->position.x >> 3);
480
self->targetPos.y = self->position.y - (self->position.y >> 3);
481
482
self->position.x += parent->position.x;
483
self->position.y += parent->position.y;
484
485
self->targetPos.x += parent->position.x;
486
self->targetPos.y += parent->position.y;
487
488
self->alpha -= 16;
489
self->timer -= 0x200;
490
491
if (self->timer < 0x400)
492
destroyEntity(self);
493
}
494
495
void KingAttack_State_LargeBullet_TwinShot(void)
496
{
497
RSDK_THIS(KingAttack);
498
499
EntityHeavyKing *king = (EntityHeavyKing *)self->parent;
500
501
RSDK.ProcessAnimation(&self->animator);
502
503
self->position = king->position;
504
505
if (king->direction)
506
self->position.x -= 0x240000;
507
else
508
self->position.x += 0x240000;
509
self->position.y -= 0x300000;
510
511
++self->timer;
512
if (!(self->timer & 6))
513
RSDK.PlaySfx(KingAttack->sfxTwinShot, false, 255);
514
515
if (!(self->timer & 3)) {
516
EntityKingAttack *attack = CREATE_ENTITY(KingAttack, INT_TO_VOID(KINGATTACK_SMALLBULLET), self->position.x, self->position.y);
517
attack->velocity.x = RSDK.Sin1024(self->angle) << 9;
518
attack->velocity.y = RSDK.Cos1024(self->angle) << 9;
519
attack->rotation = self->angle >> 1;
520
521
attack = CREATE_ENTITY(KingAttack, INT_TO_VOID(KINGATTACK_SMALLBULLET), self->position.x, self->position.y);
522
attack->velocity.x = RSDK.Sin1024(self->angle + 0x200) << 9;
523
attack->velocity.y = RSDK.Cos1024(self->angle + 0x200) << 9;
524
attack->rotation = self->angle >> 1;
525
}
526
527
self->angle += 4;
528
if (self->timer > 60) {
529
self->scale.x -= 4;
530
self->scale.y = self->scale.x;
531
532
if (!self->scale.x)
533
destroyEntity(self);
534
}
535
}
536
537
void KingAttack_State_SmallBullet(void)
538
{
539
RSDK_THIS(KingAttack);
540
541
RSDK.ProcessAnimation(&self->animator);
542
543
self->rotation = (self->rotation + 16) & 0x1FF;
544
545
self->position.x += self->velocity.x;
546
self->position.y += self->velocity.y;
547
548
KingAttack_CheckPlayerCollisions();
549
550
foreach_active(HPZEmerald, emerald)
551
{
552
if (emerald->type && RSDK.CheckObjectCollisionPlatform(emerald, emerald->hitbox, self, &self->hitbox, true)) {
553
RSDK.SetSpriteAnimation(KingAttack->aniFrames, 22, &self->animator, false, 0);
554
self->position.y += 0x40000;
555
self->state = KingAttack_State_SmallBullet_Impact;
556
foreach_break;
557
}
558
}
559
560
if (self->state == KingAttack_State_SmallBullet) {
561
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x40000, true)) {
562
RSDK.SetSpriteAnimation(KingAttack->aniFrames, 22, &self->animator, false, 0);
563
self->state = KingAttack_State_SmallBullet_Impact;
564
self->position.y += 0x40000;
565
}
566
567
if (!RSDK.CheckOnScreen(self, NULL))
568
destroyEntity(self);
569
}
570
}
571
572
void KingAttack_State_SmallBullet_Impact(void)
573
{
574
RSDK_THIS(KingAttack);
575
576
RSDK.ProcessAnimation(&self->animator);
577
578
if (self->animator.frameID == self->animator.frameCount - 1)
579
destroyEntity(self);
580
}
581
582
#if GAME_INCLUDE_EDITOR
583
void KingAttack_EditorDraw(void)
584
{
585
RSDK_THIS(KingAttack);
586
587
RSDK.SetSpriteAnimation(KingAttack->aniFrames, 20, &self->animator, true, 0);
588
589
RSDK.DrawSprite(&self->animator, NULL, false);
590
}
591
592
void KingAttack_EditorLoad(void) { KingAttack->aniFrames = RSDK.LoadSpriteAnimation("LRZ3/HeavyKing.bin", SCOPE_STAGE); }
593
#endif
594
595
void KingAttack_Serialize(void) {}
596
597