Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/SSZ/GigaMetal.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: GigaMetal Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
#if MANIA_USE_PLUS
11
ObjectGigaMetal *GigaMetal;
12
13
void GigaMetal_Update(void)
14
{
15
RSDK_THIS(GigaMetal);
16
17
StateMachine_Run(self->state);
18
}
19
20
void GigaMetal_LateUpdate(void) {}
21
22
void GigaMetal_StaticUpdate(void) {}
23
24
void GigaMetal_Draw(void)
25
{
26
RSDK_THIS(GigaMetal);
27
28
if (GigaMetal->explodeTimer <= 0) {
29
if (GigaMetal->invincibleTimer & 1) {
30
RSDK.CopyPalette(2, 32, 0, 32, 16);
31
RSDK.CopyPalette(2, 160, 0, 160, 10);
32
RSDK.CopyPalette(2, 240, 0, 240, 7);
33
34
if (self->stateDraw) {
35
StateMachine_Run(self->stateDraw);
36
}
37
else {
38
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
39
}
40
41
RSDK.CopyPalette(1, 32, 0, 32, 16);
42
RSDK.CopyPalette(1, 160, 0, 160, 10);
43
RSDK.CopyPalette(1, 240, 0, 240, 7);
44
}
45
else {
46
if (self->stateDraw) {
47
StateMachine_Run(self->stateDraw);
48
}
49
else {
50
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
51
}
52
}
53
}
54
else {
55
RSDK.SetLimitedFade(0, 4, 5, GigaMetal->explodeTimer, 0, 256);
56
57
if (self->stateDraw) {
58
StateMachine_Run(self->stateDraw);
59
}
60
else {
61
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
62
}
63
64
RSDK.CopyPalette(4, 1, 0, 1, 255);
65
}
66
}
67
68
void GigaMetal_Create(void *data)
69
{
70
RSDK_THIS(GigaMetal);
71
72
if (!SceneInfo->inEditor) {
73
if (globals->gameMode < MODE_TIMEATTACK) {
74
self->drawGroup = Zone->objectDrawGroup[0] - 1;
75
self->updateRange.x = 0x800000;
76
self->updateRange.y = 0x800000;
77
int32 slot = RSDK.GetEntitySlot(self);
78
79
if (data)
80
self->aniID = VOID_TO_INT(data);
81
82
switch (self->aniID) {
83
case GIGAMETAL_HEAD:
84
self->body = RSDK_GET_ENTITY(slot - 1, GigaMetal);
85
self->frontArm = RSDK_GET_ENTITY(slot + 3, GigaMetal);
86
self->backArm = RSDK_GET_ENTITY(slot - 2, GigaMetal);
87
self->stateDraw = GigaMetal_Draw_Head;
88
self->componentPos.x = 0x140000;
89
self->componentPos.y = -0x240000;
90
91
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_HEAD, &self->mainAnimator, true, 0);
92
break;
93
94
case GIGAMETAL_SHOULDER:
95
self->body = RSDK_GET_ENTITY(slot - 5, GigaMetal);
96
self->frontArm = RSDK_GET_ENTITY(slot - 1, GigaMetal);
97
98
self->stateDraw = GigaMetal_Draw_Shoulder;
99
self->componentPos.y = -0x2C0000;
100
self->componentPos.x = -0x240000;
101
self->drawGroup = Zone->objectDrawGroup[1];
102
103
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_SHOULDER, &self->mainAnimator, true, 0);
104
break;
105
106
case GIGAMETAL_BODY: {
107
self->head = RSDK_GET_ENTITY(slot + 1, GigaMetal);
108
self->ruby = RSDK_GET_ENTITY(slot + 2, PhantomRuby);
109
self->cover = RSDK_GET_ENTITY(slot + 3, GigaMetal);
110
self->frontArm = RSDK_GET_ENTITY(slot + 4, GigaMetal);
111
self->backArm = RSDK_GET_ENTITY(slot - 1, GigaMetal);
112
self->shoulder = RSDK_GET_ENTITY(slot + 5, GigaMetal);
113
114
self->active = ACTIVE_BOUNDS;
115
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_BODY, &self->mainAnimator, true, 0);
116
117
foreach_all(MetalSonic, metal) { self->metalSonic = metal; }
118
119
self->health = 8;
120
self->state = GigaMetal_StateBody_AwaitPlayer;
121
break;
122
}
123
124
case GIGAMETAL_COVER:
125
self->body = RSDK_GET_ENTITY(slot - 3, GigaMetal);
126
127
self->stateDraw = GigaMetal_Draw_Cover;
128
self->inkEffect = INK_ADD;
129
self->alpha = 0xFF;
130
131
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_COVER, &self->mainAnimator, true, 0);
132
break;
133
134
case GIGAMETAL_ARMFRONT:
135
self->body = RSDK_GET_ENTITY(slot - 4, GigaMetal);
136
137
self->stateDraw = GigaMetal_Draw_Arm;
138
self->componentPos.x = -0x1C0000;
139
self->componentPos.y = -0x2C0000;
140
self->drawGroup = Zone->objectDrawGroup[1];
141
142
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_ARMFRONT, &self->mainAnimator, true, 0);
143
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_ARMFRONT, &self->jointAnimator, true, 1);
144
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_ARMFRONT, &self->armAnimator, true, 2);
145
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_ARMFRONT, &self->handAnimator, true, 3);
146
break;
147
148
case GIGAMETAL_ARMBACK:
149
self->body = RSDK_GET_ENTITY(slot + 1, GigaMetal);
150
151
self->stateDraw = GigaMetal_Draw_Arm;
152
self->componentPos.x = -0xC0000;
153
self->componentPos.y = -0x2C0000;
154
155
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_ARMBACK, &self->mainAnimator, true, 0);
156
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_ARMBACK, &self->jointAnimator, true, 1);
157
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_ARMBACK, &self->armAnimator, true, 2);
158
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_ARMBACK, &self->handAnimator, true, 3);
159
break;
160
161
case GIGAMETAL_LASEREDGE:
162
self->drawFX = FX_ROTATE;
163
self->laserSize = -1;
164
self->angle = 0x40;
165
self->active = ACTIVE_NORMAL;
166
self->visible = true;
167
self->scale.x = 0x200;
168
self->scale.y = 0x200;
169
self->state = GigaMetal_State_Laser;
170
self->stateDraw = GigaMetal_Draw_LaserEdge;
171
172
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_LASEREDGE, &self->mainAnimator, true, 0);
173
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_LASERBEAM, &self->jointAnimator, true, 0);
174
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_LASEREDGE, &self->armAnimator, true, 1);
175
break;
176
177
case GIGAMETAL_SHARD:
178
self->scale.x = RSDK.Rand(0x200, 0x400);
179
self->scale.y = RSDK.Rand(0x200, 0x400);
180
self->rotationAngles[0] = RSDK.Rand(0, 0x400);
181
self->rotationAngles[1] = RSDK.Rand(0, 0x400);
182
self->rotationAngles[2] = RSDK.Rand(0, 0x400);
183
184
self->active = ACTIVE_NORMAL;
185
self->visible = true;
186
self->drawGroup = Zone->objectDrawGroup[1];
187
self->velocity.x = RSDK.Rand(-0x10000, 0x10000);
188
self->velocity.y = RSDK.Rand(-0x40000, -0x10000);
189
self->groundVel = RSDK.Rand(-16, 16);
190
191
self->state = GigaMetal_State_Shard;
192
self->stateDraw = GigaMetal_Draw_Shard;
193
break;
194
195
default: break;
196
}
197
}
198
else {
199
destroyEntity(self);
200
}
201
}
202
}
203
204
void GigaMetal_StageLoad(void)
205
{
206
GigaMetal->aniFrames = RSDK.LoadSpriteAnimation("SSZ2/GigaMetal.bin", SCOPE_STAGE);
207
208
GigaMetal->hitboxLaser.left = -12;
209
GigaMetal->hitboxLaser.top = -12;
210
GigaMetal->hitboxLaser.right = 12;
211
GigaMetal->hitboxLaser.bottom = 12;
212
213
GigaMetal->hitboxHand.left = -12;
214
GigaMetal->hitboxHand.top = -10;
215
GigaMetal->hitboxHand.right = 12;
216
GigaMetal->hitboxHand.bottom = 10;
217
218
GigaMetal->hitboxCore.left = -40;
219
GigaMetal->hitboxCore.top = -16;
220
GigaMetal->hitboxCore.right = 40;
221
GigaMetal->hitboxCore.bottom = 40;
222
223
GigaMetal->hitboxHead.left = -56;
224
GigaMetal->hitboxHead.top = -124;
225
GigaMetal->hitboxHead.right = 16;
226
GigaMetal->hitboxHead.bottom = -64;
227
228
GigaMetal->sfxRoar = RSDK.GetSfx("SSZ2/MSRoar.wav");
229
GigaMetal->sfxImpact = RSDK.GetSfx("Stage/Impact6.wav");
230
GigaMetal->sfxTarget = RSDK.GetSfx("SSZ2/MSTarget.wav");
231
GigaMetal->sfxPimpom = RSDK.GetSfx("Stage/PimPom.wav");
232
GigaMetal->sfxCannon = RSDK.GetSfx("SSZ2/MSCannon.wav");
233
234
RSDK.CopyPalette(0, 1, 4, 1, 255);
235
// Pink blend palette
236
for (int32 i = 0; i < 256; ++i) RSDK.SetPaletteEntry(5, i, 0xF00080);
237
238
GigaMetal->invincibleTimer = 0;
239
GigaMetal->explodeTimer = 0;
240
241
if (StarPost->postIDs[0]) {
242
foreach_all(Music, music)
243
{
244
if (music->playOnLoad)
245
music->trackID = TRACK_METALSONIC;
246
}
247
248
Music->restartTrackID = TRACK_METALSONIC;
249
}
250
}
251
252
void GigaMetal_Draw_Cover(void)
253
{
254
RSDK_THIS(GigaMetal);
255
256
self->position.x = self->body->position.x + self->componentPos.x;
257
self->position.y = self->body->position.y + self->componentPos.y;
258
259
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
260
}
261
262
void GigaMetal_Draw_Head(void)
263
{
264
RSDK_THIS(GigaMetal);
265
266
self->position.x = self->body->position.x + self->componentPos.x;
267
self->position.y = self->body->position.y + self->componentPos.y;
268
269
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
270
RSDK.DrawSprite(&self->jointAnimator, NULL, false);
271
RSDK.DrawSprite(&self->armAnimator, NULL, false);
272
}
273
274
void GigaMetal_Draw_Shoulder(void)
275
{
276
RSDK_THIS(GigaMetal);
277
278
self->position.x = self->body->position.x + self->componentPos.x;
279
self->position.y = self->body->position.y + self->componentPos.y;
280
281
self->position.x = MIN(3 * (self->position.x >> 2) + ((self->frontArm->position.x - 0xC0000) >> 2), self->position.x);
282
283
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
284
}
285
286
void GigaMetal_Draw_Arm(void)
287
{
288
RSDK_THIS(GigaMetal);
289
Vector2 drawPos;
290
291
self->position.x = self->body->position.x + self->componentPos.x;
292
self->position.y = self->body->position.y + self->componentPos.y;
293
294
int32 angle = self->rotationAngles[0] >> 6;
295
drawPos.x = (RSDK.Sin1024(angle) << 11) + self->position.x;
296
drawPos.y = (RSDK.Cos1024(angle) << 11) + self->position.y;
297
self->position.x = drawPos.x;
298
self->position.y = drawPos.y;
299
RSDK.DrawSprite(&self->mainAnimator, &drawPos, false);
300
301
angle += (self->rotationAngles[1] >> 6);
302
drawPos.x += 0x600 * RSDK.Sin1024(angle);
303
drawPos.y += 0x600 * RSDK.Cos1024(angle);
304
305
if (self->mainAnimator.animationID == GIGAMETAL_ARMFRONT) {
306
self->drawFX = FX_ROTATE;
307
self->rotation = -(angle >> 1);
308
RSDK.DrawSprite(&self->armAnimator, &drawPos, false);
309
310
self->drawFX = FX_NONE;
311
RSDK.DrawSprite(&self->jointAnimator, &drawPos, false);
312
}
313
else {
314
RSDK.DrawSprite(&self->jointAnimator, &drawPos, false);
315
316
self->drawFX = FX_ROTATE;
317
self->rotation = -(angle >> 1);
318
RSDK.DrawSprite(&self->armAnimator, &drawPos, false);
319
320
self->drawFX = FX_NONE;
321
}
322
323
drawPos.x += RSDK.Sin1024(angle) << 9;
324
drawPos.y += RSDK.Cos1024(angle) << 9;
325
326
angle += 0x100;
327
drawPos.x += 0x1500 * RSDK.Sin1024(angle);
328
drawPos.y += 0x1500 * RSDK.Cos1024(angle);
329
self->drawFX = FX_ROTATE;
330
self->rotation = -((angle + ((self->rotationAngles[2] >> 6) - 256)) >> 1);
331
RSDK.DrawSprite(&self->handAnimator, &drawPos, false);
332
333
self->drawFX = FX_NONE;
334
}
335
336
void GigaMetal_Draw_LaserEdge(void)
337
{
338
RSDK_THIS(GigaMetal);
339
340
Vector2 drawPos;
341
self->position.x = self->body->position.x;
342
self->position.y = self->body->position.y;
343
344
// Draw Laser Edge (Bit that emits laser)
345
int32 angle = self->angle - self->body->rotation;
346
self->rotation = self->angle + self->body->rotation;
347
drawPos.x = (RSDK.Sin512(angle + 8) << 12) + self->position.x;
348
drawPos.y = (RSDK.Cos512(angle + 8) << 12) + self->position.y;
349
RSDK.DrawSprite(&self->mainAnimator, &drawPos, false);
350
351
int32 moveX = (RSDK.Sin512(angle) << 12) & 0xFFFF0000;
352
int32 moveY = (RSDK.Cos512(angle) << 12) & 0xFFFF0000;
353
354
// Draw Laser
355
for (int32 i = 0; i < self->laserSize; ++i) {
356
RSDK.DrawSprite(&self->jointAnimator, &drawPos, false);
357
drawPos.x += moveX;
358
drawPos.y += moveY;
359
}
360
361
// Draw Laser Edge (Bit that hits the ground)
362
RSDK.DrawSprite(&self->armAnimator, &drawPos, false);
363
}
364
365
void GigaMetal_Draw_Shard(void)
366
{
367
RSDK_THIS(GigaMetal);
368
369
Vector2 vertices[3];
370
371
int32 x = ScreenInfo[SceneInfo->currentScreenID].position.x << 16;
372
int32 y = ScreenInfo[SceneInfo->currentScreenID].position.y << 16;
373
374
int32 angle = self->angle + self->rotationAngles[0];
375
vertices[0].x = self->scale.x * RSDK.Sin1024(angle) - x + self->position.x;
376
vertices[0].y = self->scale.y * RSDK.Cos1024(angle) + self->position.y - y;
377
378
angle = self->angle + self->rotationAngles[1];
379
vertices[1].x = self->scale.x * RSDK.Sin1024(angle) - x + self->position.x;
380
vertices[1].y = self->scale.y * RSDK.Cos1024(angle) + self->position.y - y;
381
382
angle = self->angle + self->rotationAngles[2];
383
vertices[2].x = self->scale.x * RSDK.Sin1024(angle) - x + self->position.x;
384
vertices[2].y = self->scale.y * RSDK.Cos1024(angle) + self->position.y - y;
385
386
RSDK.DrawFace(vertices, 3, 0xF0, 0x00, 0x80, 0xFF, INK_ADD);
387
}
388
389
void GigaMetal_HandleCameraMovement(void)
390
{
391
Zone->cameraBoundsL[0] += 2;
392
Zone->cameraBoundsR[0] += 2;
393
394
EntityCamera *camera = RSDK_GET_ENTITY(SLOT_CAMERA1, Camera);
395
camera->boundsL = Zone->cameraBoundsL[0];
396
camera->boundsR = Zone->cameraBoundsR[0];
397
camera->position.x = (Zone->cameraBoundsR[0] + camera->boundsL) << 15;
398
399
MetalSonic_HandleStageWrap();
400
}
401
402
void GigaMetal_CheckPlayerCollisions(void)
403
{
404
RSDK_THIS(GigaMetal);
405
406
if (GigaMetal->invincibleTimer > 0)
407
GigaMetal->invincibleTimer--;
408
409
foreach_active(Player, player)
410
{
411
if (Player_CheckCollisionTouch(player, self, &GigaMetal->hitboxHead) && player->velocity.x < 0 && Player_CheckBossHit(player, self)) {
412
player->velocity.x = abs(player->velocity.x) + Zone->autoScrollSpeed;
413
RSDK.PlaySfx(GigaMetal->sfxPimpom, false, 0xFF);
414
}
415
}
416
417
foreach_active(Player, playerPtr)
418
{
419
if (!GigaMetal->invincibleTimer && Player_CheckBadnikTouch(playerPtr, self, &GigaMetal->hitboxCore) && Player_CheckBossHit(playerPtr, self)) {
420
playerPtr->velocity.x += Zone->autoScrollSpeed;
421
GigaMetal_Hit();
422
}
423
}
424
}
425
426
void GigaMetal_Hit(void)
427
{
428
RSDK_THIS(GigaMetal);
429
430
if (--self->health <= 0) {
431
EntityGigaMetal *head = self->head;
432
EntityGigaMetal *frontArm = self->frontArm;
433
EntityGigaMetal *backArm = self->backArm;
434
head->state = StateMachine_None;
435
frontArm->state = StateMachine_None;
436
backArm->state = StateMachine_None;
437
438
self->timer = 0;
439
self->state = GigaMetal_StateBody_Destroyed;
440
SceneInfo->timeEnabled = false;
441
Player_GiveScore(RSDK_GET_ENTITY(SLOT_PLAYER1, Player), 1000);
442
}
443
else {
444
GigaMetal->invincibleTimer = 40;
445
RSDK.PlaySfx(MetalSonic->sfxHit, false, 255);
446
447
EntityGigaMetal *cover = self->cover;
448
++cover->mainAnimator.frameID;
449
}
450
}
451
452
void GigaMetal_StateBody_AwaitPlayer(void)
453
{
454
RSDK_THIS(GigaMetal);
455
456
EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
457
if (player1->position.y < self->position.y && !player1->collisionPlane) {
458
459
Zone->playerBoundActiveL[0] = true;
460
Zone->playerBoundActiveR[0] = true;
461
462
Zone->cameraBoundsL[0] = FROM_FIXED(self->position.x) - ScreenInfo->center.x + 32;
463
Zone->cameraBoundsR[0] = FROM_FIXED(self->position.x) + ScreenInfo->center.x + 32;
464
Zone->cameraBoundsT[0] = FROM_FIXED(self->position.y) - ScreenInfo->size.y + 16;
465
Zone->cameraBoundsB[0] = FROM_FIXED(self->position.y) + 16;
466
Zone->deathBoundary[0] = FROM_FIXED(self->position.y) + 16;
467
468
EntityMetalSonic *metal = self->metalSonic;
469
if (metal) {
470
if (!metal->onScreen) {
471
metal->position.x = self->position.x - 0xC00000;
472
metal->position.y = self->position.y + 0x400000;
473
}
474
metal->angle = 0;
475
metal->targetPos.x = self->position.x - 0x400000;
476
metal->targetPos.y = self->position.y - 0x500000;
477
metal->timer = 0;
478
metal->visible = true;
479
metal->active = ACTIVE_NORMAL;
480
metal->state = MetalSonic_State_WaitForRuby;
481
RSDK.SetSpriteAnimation(MetalSonic->aniFrames, MS_ANI_HOVER, &metal->metalSonicAnimator, false, 0);
482
RSDK.SetSpriteAnimation(MetalSonic->aniFrames, MS_ANI_BOOSTER_WEAK, &metal->boosterAnimator, false, 0);
483
}
484
485
self->position.x -= 0x500000;
486
self->position.y -= 0x380000;
487
self->active = ACTIVE_NORMAL;
488
self->state = GigaMetal_StateBody_SetupComponents;
489
490
foreach_all(BoundsMarker, marker) { destroyEntity(marker); }
491
}
492
}
493
494
void GigaMetal_StateBody_SetupComponents(void)
495
{
496
RSDK_THIS(GigaMetal);
497
498
EntityMetalSonic *metal = self->metalSonic;
499
500
// Wait for metal sonic to become inactive (should happen during the white flash)
501
if (metal->active == ACTIVE_NEVER) {
502
EntityGigaMetal *head = self->head;
503
head->visible = true;
504
head->active = ACTIVE_NORMAL;
505
506
EntityPhantomRuby *ruby = self->ruby;
507
ruby->startPos.x = self->position.x + 0x200000;
508
ruby->startPos.y = self->position.y + 0x100000;
509
ruby->drawGroup = self->drawGroup;
510
ruby->position.x = ruby->startPos.x;
511
ruby->position.y = ruby->startPos.y;
512
513
EntityGigaMetal *cover = self->cover;
514
cover->visible = true;
515
cover->active = ACTIVE_NORMAL;
516
517
EntityGigaMetal *shoulder = self->shoulder;
518
shoulder->visible = true;
519
shoulder->active = ACTIVE_NORMAL;
520
521
EntityGigaMetal *frontArm = self->frontArm;
522
frontArm->visible = true;
523
frontArm->active = ACTIVE_NORMAL;
524
frontArm->state = GigaMetal_StateArm_Idle_Front;
525
526
EntityGigaMetal *backArm = self->backArm;
527
backArm->visible = true;
528
backArm->active = ACTIVE_NORMAL;
529
backArm->state = GigaMetal_StateArm_Idle_Front;
530
531
self->visible = true;
532
self->state = GigaMetal_StateBody_Transformed;
533
RSDK.CopyTileLayer(Zone->fgLayer[1], 0, 34, Zone->fgLayer[1], 0, 26, 256, 6);
534
535
foreach_active(Player, player)
536
{
537
if (player->position.x < self->position.x + 0xE00000)
538
player->position.x = self->position.x + 0xE00000;
539
540
player->position.y = ruby->position.y + 0x80000;
541
player->groundVel = 0;
542
player->velocity.x = 0;
543
}
544
}
545
}
546
547
void GigaMetal_StateBody_Transformed(void)
548
{
549
RSDK_THIS(GigaMetal);
550
551
if (++self->timer == 120) {
552
EntityGigaMetal *head = self->head;
553
head->state = GigaMetal_StateHead_PrepareRoar;
554
555
EntityGigaMetal *frontArm = self->frontArm;
556
frontArm->state = GigaMetal_StateArm_Idle_Behind;
557
558
EntityGigaMetal *backArm = self->backArm;
559
backArm->state = GigaMetal_StateArm_Idle_Behind;
560
561
self->timer = 0;
562
self->state = GigaMetal_StateBody_Roar;
563
}
564
}
565
566
void GigaMetal_StateBody_Roar(void)
567
{
568
RSDK_THIS(GigaMetal);
569
570
++self->timer;
571
if (!(self->timer & 7))
572
Camera_ShakeScreen(0, 0, 4);
573
574
if (self->timer == 120) {
575
EntityGigaMetal *head = self->head;
576
head->state = GigaMetal_StateHead_FinishRoar;
577
578
EntityGigaMetal *frontArm = self->frontArm;
579
frontArm->timer = 48;
580
frontArm->state = GigaMetal_StateArm_Marching;
581
582
EntityGigaMetal *backArm = self->backArm;
583
backArm->timer = 48;
584
backArm->angle = 128;
585
backArm->state = GigaMetal_StateArm_Marching;
586
587
self->targetPos.x = self->position.x;
588
self->targetPos.y = self->position.y + 0x80000;
589
self->timer = 320;
590
self->velocity.x = 0x20000;
591
self->state = GigaMetal_StateBody_Marching;
592
Zone->autoScrollSpeed = 0x20000;
593
}
594
}
595
596
void GigaMetal_StateBody_Marching(void)
597
{
598
RSDK_THIS(GigaMetal);
599
600
self->position.x += self->velocity.x;
601
602
if ((RSDK.Sin256(self->angle) & 0x200000) != 0)
603
self->position.y = self->targetPos.y - -(RSDK.Sin256(self->angle) << 10);
604
else
605
self->position.y = self->targetPos.y - (RSDK.Sin256(self->angle) << 10);
606
607
self->angle = (self->angle + 2) & 0xFF;
608
609
EntityPhantomRuby *ruby = self->ruby;
610
ruby->position.x = self->position.x + 0x200000;
611
ruby->startPos.y = self->position.y + 0x100000;
612
613
EntityGigaMetal *head = self->head;
614
if (!(self->angle & 0x7F)) {
615
if (!head->state) {
616
head->targetPos.x = head->componentPos.x;
617
head->targetPos.y = head->componentPos.y;
618
head->velocity.y = 0x10000;
619
head->state = GigaMetal_StateHead_Impact;
620
RSDK.PlaySfx(GigaMetal->sfxImpact, false, 255);
621
}
622
623
EntityGigaMetal *shoulder = self->shoulder;
624
shoulder->targetPos.x = shoulder->componentPos.x;
625
shoulder->targetPos.y = shoulder->componentPos.y;
626
shoulder->velocity.y = -0x12000;
627
shoulder->state = GigaMetal_StateShoulder_Impact;
628
629
Camera_ShakeScreen(0, 0, 4);
630
}
631
632
if (!head->state || head->state == GigaMetal_StateHead_Impact)
633
--self->timer;
634
635
if (self->timer <= 0) {
636
EntityGigaMetal *frontArm = self->frontArm;
637
EntityGigaMetal *backArm = self->backArm;
638
639
self->timer = RSDK.Rand(240, 480);
640
if (RSDK.Rand(0, 1024) <= 0x200) {
641
if (self->attackTimer & 0xFFFFFF00)
642
self->attackTimer = 0;
643
else
644
self->attackTimer++;
645
646
if ((self->attackTimer & 0xFF) > 2)
647
self->attackTimer = 0x100;
648
}
649
else {
650
if ((self->attackTimer & 0xFFFFFF00) == 0x100)
651
++self->attackTimer;
652
else
653
self->attackTimer = 0x100;
654
655
if ((self->attackTimer & 0xFF) > 2)
656
self->attackTimer = 0;
657
}
658
659
head->state = (self->attackTimer & 0xFFFFFF00) == 0x100 ? GigaMetal_StateHead_TargetingPlayer : GigaMetal_StateHead_PrepareLaser;
660
661
frontArm->state = GigaMetal_StateArm_Idle_Behind;
662
backArm->state = GigaMetal_StateArm_Idle_Behind;
663
}
664
665
GigaMetal_HandleCameraMovement();
666
GigaMetal_CheckPlayerCollisions();
667
668
if ((Zone->timer & 7) == 2) {
669
int32 endX = ((ScreenInfo->size.x + ScreenInfo->position.x) >> 4) + 1;
670
int32 endY = (ScreenInfo->size.y + ScreenInfo->position.y) >> 4;
671
672
RSDK.CopyTileLayer(Zone->fgLayer[1], endX, endY - 5, Zone->fgLayer[1], endX, endY - 5 + 8, 1, 6);
673
if (endX > 224)
674
RSDK.CopyTileLayer(Zone->fgLayer[1], endX - 224, endY - 5, Zone->fgLayer[1], endX - 224, endY - 5 + 8, 1, 6);
675
676
int32 tileX = (ScreenInfo->position.x >> 4) + 8;
677
int32 spawnY = (endY << 20) + 0x80000;
678
679
for (int32 delay = 4; delay < 40; delay += 6) {
680
uint16 tile = RSDK.GetTile(Zone->fgLayer[1], tileX, endY);
681
682
if (tile != (uint16)-1) {
683
EntityBreakableWall *block = CREATE_ENTITY(BreakableWall, INT_TO_VOID(BREAKWALL_TILE_DYNAMIC), (tileX << 20) + 0x80000, spawnY);
684
block->drawGroup = Zone->objectDrawGroup[1];
685
block->targetLayer = Zone->fgLayer[1];
686
block->tileInfo = tile;
687
block->tilePos.x = tileX;
688
block->tilePos.y = endY;
689
block->timer = delay;
690
block->active = ACTIVE_NORMAL;
691
692
if (tileX > 224) {
693
block = CREATE_ENTITY(BreakableWall, INT_TO_VOID(BREAKWALL_TILE_DYNAMIC), (tileX << 20) - 0xDF80000, spawnY);
694
block->drawGroup = Zone->objectDrawGroup[1];
695
block->targetLayer = Zone->fgLayer[1];
696
block->tileInfo = tile;
697
block->tilePos.y = endY;
698
block->tilePos.x = tileX - 224;
699
block->timer = delay;
700
block->updateRange.x = 0x10000000;
701
block->active = ACTIVE_NORMAL;
702
}
703
}
704
705
--endY;
706
spawnY -= 0x100000;
707
}
708
}
709
}
710
711
void GigaMetal_StateBody_Destroyed(void)
712
{
713
RSDK_THIS(GigaMetal);
714
715
self->velocity.y += 0x1000;
716
self->position.y += self->velocity.y;
717
718
if (self->position.y >= self->targetPos.y) {
719
EntityGigaMetal *head = self->head;
720
self->velocity.y = -0xC000;
721
head->velocity.y = 0x18000;
722
head->targetPos = head->componentPos;
723
head->state = GigaMetal_StateHead_Impact;
724
725
EntityGigaMetal *shoulder = self->shoulder;
726
shoulder->velocity.y = -0x18000;
727
shoulder->targetPos = shoulder->componentPos;
728
shoulder->state = GigaMetal_StateShoulder_Impact;
729
Camera_ShakeScreen(0, 0, 4);
730
}
731
732
EntityPhantomRuby *ruby = self->ruby;
733
ruby->position.x = self->position.x + 0x200000;
734
ruby->startPos.y = self->position.y + 0x100000;
735
736
if (!(Zone->timer & 7)) {
737
int32 x = self->position.x + RSDK.Rand(-0x600000, 0x600000);
738
int32 y = self->position.y + RSDK.Rand(-0x600000, 0x600000);
739
CREATE_ENTITY(Explosion, INT_TO_VOID((RSDK.Rand(0, 256) > 192) + EXPLOSION_BOSS), x, y)->drawGroup = Zone->objectDrawGroup[1];
740
}
741
742
if (!(Zone->timer % 6))
743
RSDK.PlaySfx(MetalSonic->sfxExplosion2, false, 255);
744
745
if ((Zone->timer & 0x3F) == 32)
746
RSDK.PlaySfx(MSBomb->sfxExplosion, false, 255);
747
748
foreach_active(Player, player)
749
{
750
if (player->position.x < self->position.x + 0x400000) {
751
player->velocity.x = 0x40000;
752
753
if (player->velocity.y >= 0) {
754
player->velocity.y = -0x40000;
755
player->onGround = false;
756
RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, false, 0);
757
}
758
}
759
}
760
761
if (GigaMetal->explodeTimer >= 240) {
762
GigaMetal->explodeTimer = 0;
763
EntityMetalSonic *metal = self->metalSonic;
764
765
metal->position.x = self->position.x - 0x100000;
766
metal->position.y = self->position.y - 0x200000;
767
metal->active = ACTIVE_NORMAL;
768
metal->state = MetalSonic_State_Defeated;
769
metal->velocity.x = 0;
770
metal->velocity.y = -0x40000;
771
RSDK.SetSpriteAnimation(MetalSonic->aniFrames, MS_ANI_DEFEATED, &metal->metalSonicAnimator, false, 0);
772
773
foreach_active(GigaMetal, part) { destroyEntity(part); }
774
775
for (int32 i = 0; i < 0x40; ++i) {
776
int32 x = metal->position.x + RSDK.Rand(-0x600000, 0x400000);
777
int32 y = metal->position.y + RSDK.Rand(-0x600000, 0x600000);
778
CREATE_ENTITY(GigaMetal, INT_TO_VOID(GIGAMETAL_SHARD), x, y);
779
}
780
781
EntityFXFade *fxFade = CREATE_ENTITY(FXFade, INT_TO_VOID(0xF0F0F0), self->position.x, self->position.y);
782
fxFade->speedIn = 256;
783
fxFade->speedOut = 64;
784
Zone->autoScrollSpeed = 0;
785
RSDK.PlaySfx(MetalSonic->sfxExplosion3, false, 255);
786
787
EntityDango *dango = CREATE_ENTITY(Dango, NULL, (ScreenInfo->position.x - 64) << 16, (ScreenInfo->position.y + 200) << 16);
788
dango->timer = 0;
789
dango->direction = FLIP_X;
790
dango->state = Dango_StateTaunt_Setup;
791
792
int32 tileX = ScreenInfo->position.x >> 4;
793
int32 tileY = ((ScreenInfo->size.y + ScreenInfo->position.y) >> 4) - 5;
794
795
int32 spawnX = (tileX << 20) + 0x80000;
796
for (int32 x = 0; x < 32; ++x) {
797
int32 spawnY = (tileY << 20) + 0x80000;
798
799
for (int32 y = 0; y < 6; ++y) {
800
uint16 tile = RSDK.GetTile(Zone->fgLayer[1], tileX, tileY);
801
802
if (tile != (uint16)-1) {
803
RSDK.SetTile(Zone->fgLayer[1], tileX, tileY, -1);
804
EntityBreakableWall *block = CREATE_ENTITY(BreakableWall, INT_TO_VOID(BREAKWALL_TILE_FIXED), spawnX, spawnY);
805
block->drawGroup = Zone->objectDrawGroup[1];
806
block->visible = true;
807
block->tileInfo = tile;
808
block->velocity.x = RSDK.Rand(-0x20000, 0x20000);
809
block->velocity.y = RSDK.Rand(-0x20000, 0x20000);
810
block->drawFX = FX_ROTATE | FX_FLIP;
811
}
812
813
++tileY;
814
spawnY += 0x100000;
815
}
816
817
spawnX += 0x100000;
818
tileY -= 6;
819
++tileX;
820
}
821
822
RSDK.CopyTileLayer(Zone->fgLayer[0], 0, 30, Zone->fgLayer[0], 0, 174, 256, 2);
823
RSDK.CopyTileLayer(Zone->fgLayer[1], 0, 26, Zone->fgLayer[0], 0, 0, 256, 6);
824
}
825
else {
826
GigaMetal->explodeTimer++;
827
}
828
}
829
830
void GigaMetal_StateShoulder_Impact(void)
831
{
832
RSDK_THIS(GigaMetal);
833
834
self->velocity.y += 0x3800;
835
self->componentPos.y += self->velocity.y;
836
837
if (self->velocity.y > 0) {
838
if (self->componentPos.y >= self->targetPos.y) {
839
self->componentPos.y = self->targetPos.y;
840
self->velocity.y = -(self->velocity.y >> 2);
841
if (self->velocity.y > -0x800) {
842
self->velocity.y = 0;
843
self->state = StateMachine_None;
844
}
845
}
846
}
847
}
848
849
void GigaMetal_StateHead_Impact(void)
850
{
851
RSDK_THIS(GigaMetal);
852
853
self->velocity.y -= 0x3800;
854
self->componentPos.y += self->velocity.y;
855
856
if (self->velocity.y < 0) {
857
if (self->componentPos.y <= self->targetPos.y) {
858
self->componentPos.y = self->targetPos.y;
859
self->velocity.y = -(self->velocity.y >> 2);
860
861
if (self->velocity.y < 0x4000) {
862
self->velocity.y = 0;
863
self->state = StateMachine_None;
864
}
865
}
866
}
867
}
868
869
void GigaMetal_State_Laser(void)
870
{
871
RSDK_THIS(GigaMetal);
872
873
RSDK.ProcessAnimation(&self->jointAnimator);
874
875
if (!(Zone->timer & 1)) {
876
if (self->laserSize < 9)
877
self->laserSize++;
878
}
879
880
self->position.x = self->body->position.x;
881
self->position.y = self->body->position.y;
882
883
int32 angle = self->angle - self->body->rotation;
884
int32 x = self->position.x + (RSDK.Sin512(angle + 8) << 12);
885
int32 y = self->position.y + (RSDK.Cos512(angle + 8) << 12);
886
int32 moveX = (RSDK.Sin512(angle) << 12) & 0xFFFF0000;
887
int32 moveY = (RSDK.Cos512(angle) << 12) & 0xFFFF0000;
888
889
for (int32 c = 0; c < self->laserSize; ++c) {
890
self->position.x = x;
891
self->position.y = y;
892
893
foreach_active(Player, player)
894
{
895
if (Player_CheckCollisionTouch(player, self, &GigaMetal->hitboxLaser) && Player_ElementHurt(player, self, SHIELD_LIGHTNING))
896
player->velocity.x = abs(player->velocity.x) + Zone->autoScrollSpeed;
897
}
898
899
if (!(Zone->timer & 3)) {
900
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x20000, true))
901
CREATE_ENTITY(Explosion, NULL, self->position.x, self->position.y);
902
}
903
904
x += moveX;
905
y += moveY;
906
}
907
}
908
909
void GigaMetal_StateLaser_Finish(void)
910
{
911
RSDK_THIS(GigaMetal);
912
913
RSDK.ProcessAnimation(&self->jointAnimator);
914
915
if (self->scale.y <= 8)
916
destroyEntity(self);
917
else
918
self->scale.y -= 8;
919
}
920
921
void GigaMetal_State_Shard(void)
922
{
923
RSDK_THIS(GigaMetal);
924
925
self->velocity.y += 0x3800;
926
self->position.x += self->velocity.x;
927
self->position.y += self->velocity.y;
928
self->angle += self->groundVel;
929
930
if (!RSDK.CheckOnScreen(self, NULL))
931
destroyEntity(self);
932
}
933
934
void GigaMetal_StateHead_PrepareRoar(void)
935
{
936
RSDK_THIS(GigaMetal);
937
938
self->drawFX = FX_ROTATE;
939
940
if (self->rotation <= -32) {
941
self->state = GigaMetal_StateHead_Roar;
942
943
RSDK.PlaySfx(GigaMetal->sfxRoar, false, 255);
944
}
945
else {
946
self->rotation -= 2;
947
}
948
}
949
950
void GigaMetal_StateHead_Roar(void)
951
{
952
RSDK_THIS(GigaMetal);
953
954
self->rotation = RSDK.Rand(-34, -30);
955
}
956
957
void GigaMetal_StateHead_FinishRoar(void)
958
{
959
RSDK_THIS(GigaMetal);
960
961
if (self->rotation >= 0) {
962
self->rotation = 0;
963
self->drawFX = FX_NONE;
964
self->state = StateMachine_None;
965
}
966
else {
967
self->rotation += 2;
968
}
969
}
970
971
void GigaMetal_StateHead_PrepareLaser(void)
972
{
973
RSDK_THIS(GigaMetal);
974
975
self->drawFX = FX_ROTATE;
976
977
if (self->rotation <= -64) {
978
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_LASERCHARGE, &self->armAnimator, false, 0);
979
self->state = GigaMetal_StateHead_ChargeLaser;
980
981
RSDK.PlaySfx(GigaMetal->sfxRoar, false, 255);
982
}
983
else {
984
self->rotation -= 2;
985
}
986
}
987
988
void GigaMetal_StateHead_ChargeLaser(void)
989
{
990
RSDK_THIS(GigaMetal);
991
992
// Shaking effect
993
self->rotation = RSDK.Rand(-66, -62);
994
995
RSDK.ProcessAnimation(&self->armAnimator);
996
997
if (++self->timer == 120) {
998
self->timer = 0;
999
self->state = GigaMetal_StateHead_FiringLaser;
1000
CREATE_ENTITY(GigaMetal, INT_TO_VOID(GIGAMETAL_LASEREDGE), self->position.x, self->position.y)->body = self;
1001
RSDK.PlaySfx(MetalSonic->sfxMSFireball, false, 255);
1002
}
1003
}
1004
1005
void GigaMetal_StateHead_FiringLaser(void)
1006
{
1007
RSDK_THIS(GigaMetal);
1008
1009
RSDK.ProcessAnimation(&self->armAnimator);
1010
1011
if (self->rotation >= 0) {
1012
if (++self->timer == 2) {
1013
RSDK.SetSpriteAnimation(-1, 0, &self->armAnimator, false, 0);
1014
1015
foreach_active(GigaMetal, laser)
1016
{
1017
if (laser->state == GigaMetal_State_Laser) {
1018
laser->drawFX |= FX_SCALE;
1019
laser->alpha = 0xA0;
1020
laser->state = GigaMetal_StateLaser_Finish;
1021
}
1022
}
1023
}
1024
else if (self->timer == 30) {
1025
self->timer = 0;
1026
1027
foreach_active(GigaMetal, arm)
1028
{
1029
if (arm->state == GigaMetal_StateArm_Idle_Behind) {
1030
arm->angle = arm->body->angle;
1031
if (arm->mainAnimator.animationID == GIGAMETAL_ARMBACK)
1032
arm->angle += 0x80;
1033
arm->timer = 48;
1034
arm->state = GigaMetal_StateArm_Marching;
1035
}
1036
}
1037
1038
self->rotation = 0;
1039
self->drawFX = FX_NONE;
1040
self->state = StateMachine_None;
1041
}
1042
}
1043
else {
1044
self->rotation++;
1045
}
1046
}
1047
1048
void GigaMetal_StateHead_TargetingPlayer(void)
1049
{
1050
RSDK_THIS(GigaMetal);
1051
1052
++self->timer;
1053
RSDK.ProcessAnimation(&self->jointAnimator);
1054
1055
if (self->timer == 1) {
1056
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_EYE, &self->jointAnimator, false, 3);
1057
}
1058
else if (self->timer == 88) {
1059
RSDK.SetSpriteAnimation(-1, 0, &self->jointAnimator, false, 0);
1060
self->targetPos = self->componentPos;
1061
self->timer = 0;
1062
self->state = GigaMetal_StateHead_ReleasingBombs;
1063
}
1064
1065
bool32 playTargetingSfx = false;
1066
if (self->timer >= 72)
1067
playTargetingSfx = (self->timer & 7) == 1;
1068
else
1069
playTargetingSfx = (self->timer % 20) == 1;
1070
1071
if (playTargetingSfx)
1072
RSDK.PlaySfx(GigaMetal->sfxTarget, false, 255);
1073
}
1074
1075
void GigaMetal_StateHead_ReleasingBombs(void)
1076
{
1077
RSDK_THIS(GigaMetal);
1078
1079
self->timer++;
1080
if ((self->timer % 90) == 1) {
1081
self->velocity.x = -0x8000;
1082
EntityMSBomb *bomb = CREATE_ENTITY(MSBomb, NULL, self->position.x + 0x100000, self->position.y + 0xC0000);
1083
1084
bomb->velocity.x = 0x40000;
1085
bomb->velocity.y = 0x40000;
1086
RSDK.PlaySfx(GigaMetal->sfxCannon, false, 255);
1087
}
1088
1089
self->componentPos.x += self->velocity.x;
1090
self->componentPos.y += self->velocity.x;
1091
self->velocity.x += 0x3800;
1092
1093
if (self->componentPos.x > self->targetPos.x) {
1094
self->componentPos.x = self->targetPos.x;
1095
self->componentPos.y = self->targetPos.y;
1096
self->velocity.x = 0;
1097
}
1098
1099
if (self->timer == 224) {
1100
EntityGigaMetal *frontArm = self->frontArm;
1101
self->timer = 0;
1102
frontArm->timer = 48;
1103
frontArm->angle = 0;
1104
frontArm->state = GigaMetal_StateArm_Marching;
1105
1106
EntityGigaMetal *backArm = self->backArm;
1107
backArm->timer = 48;
1108
backArm->angle = 128;
1109
backArm->state = GigaMetal_StateArm_Marching;
1110
self->state = 0;
1111
}
1112
}
1113
1114
void GigaMetal_HandleArmCollisions(void)
1115
{
1116
RSDK_THIS(GigaMetal);
1117
1118
if (self->mainAnimator.animationID != GIGAMETAL_ARMBACK) {
1119
int32 angle = self->rotationAngles[0] >> 6;
1120
1121
self->position.x = self->body->position.x + self->componentPos.x + (RSDK.Sin1024(angle) << 11);
1122
self->position.y = self->body->position.y + self->componentPos.y + (RSDK.Cos1024(angle) << 11);
1123
1124
angle += self->rotationAngles[1] >> 6;
1125
self->position.x += 0x600 * RSDK.Sin1024(angle);
1126
self->position.y += 0x600 * RSDK.Cos1024(angle);
1127
self->position.x += RSDK.Sin1024(angle) << 9;
1128
1129
angle += 0x100;
1130
self->position.y += RSDK.Cos1024(angle) << 9;
1131
self->position.x += 0x1500 * RSDK.Sin1024(angle);
1132
self->position.y += 0x1500 * RSDK.Cos1024(angle);
1133
1134
angle += self->rotationAngles[2] >> 6;
1135
self->position.x += 0x600 * RSDK.Sin1024(angle);
1136
self->position.y += 0x600 * RSDK.Cos1024(angle);
1137
1138
foreach_active(Player, player)
1139
{
1140
if (!GigaMetal->invincibleTimer) {
1141
if (Player_CheckCollisionTouch(player, self, &GigaMetal->hitboxHand)
1142
&& !Player_CheckMightyUnspin(player, 0x400, false, &player->uncurlTimer) && Player_Hurt(player, self)) {
1143
player->velocity.x = abs(player->velocity.x) + Zone->autoScrollSpeed;
1144
}
1145
}
1146
}
1147
}
1148
}
1149
1150
void GigaMetal_StateArm_Idle_Front(void)
1151
{
1152
RSDK_THIS(GigaMetal);
1153
1154
self->rotationAngles[0] = RSDK.Sin256(self->timer) - 0x800;
1155
self->rotationAngles[1] = RSDK.Sin256(self->timer) - 0x200;
1156
self->rotationAngles[2] = RSDK.Sin256(self->timer) + 0xC00;
1157
self->timer = (self->timer + 2) & 0xFF;
1158
1159
GigaMetal_HandleArmCollisions();
1160
}
1161
1162
void GigaMetal_StateArm_Idle_Behind(void)
1163
{
1164
RSDK_THIS(GigaMetal);
1165
1166
if (self->rotationAngles[0] >= -0x1F00) {
1167
self->rotationAngles[0] += ((-0x2000 - self->rotationAngles[0]) >> 3);
1168
self->rotationAngles[1] += (-0x1000 - self->rotationAngles[1]) >> 3;
1169
self->rotationAngles[2] += ((0x1000 - self->rotationAngles[2]) >> 3);
1170
}
1171
else {
1172
self->rotationAngles[1] = RSDK.Rand(-0x1200, -0xE00);
1173
}
1174
1175
GigaMetal_HandleArmCollisions();
1176
}
1177
1178
void GigaMetal_StateArm_Marching(void)
1179
{
1180
RSDK_THIS(GigaMetal);
1181
1182
int32 angle1 = 16 * RSDK.Sin256(self->angle);
1183
int32 angle2 = 4 * RSDK.Sin256(self->angle);
1184
int32 angle3 = 4 * RSDK.Sin256(self->angle - 0x40);
1185
1186
if (self->timer > 0) {
1187
angle1 = self->rotationAngles[0] + ((angle1 - self->rotationAngles[0]) >> 2);
1188
angle2 = self->rotationAngles[1] + ((angle2 - self->rotationAngles[1]) >> 2);
1189
angle3 = self->rotationAngles[2] + ((angle3 - self->rotationAngles[2]) >> 2);
1190
--self->timer;
1191
}
1192
1193
self->rotationAngles[0] = angle1;
1194
self->rotationAngles[1] = angle2;
1195
self->rotationAngles[2] = angle3;
1196
self->angle = (self->angle + 2) & 0xFF;
1197
1198
GigaMetal_HandleArmCollisions();
1199
}
1200
1201
#if GAME_INCLUDE_EDITOR
1202
void GigaMetal_EditorDraw(void)
1203
{
1204
RSDK_THIS(GigaMetal);
1205
1206
switch (self->aniID) {
1207
case GIGAMETAL_HEAD:
1208
self->componentPos.x = 0x140000;
1209
self->componentPos.y = -0x240000;
1210
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_HEAD, &self->mainAnimator, true, 0);
1211
1212
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
1213
break;
1214
1215
case GIGAMETAL_SHOULDER:
1216
self->componentPos.x = -0x240000;
1217
self->componentPos.y = -0x2C0000;
1218
self->drawGroup = Zone->objectDrawGroup[1];
1219
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_SHOULDER, &self->mainAnimator, true, 0);
1220
1221
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
1222
break;
1223
1224
case GIGAMETAL_BODY:
1225
self->active = ACTIVE_BOUNDS;
1226
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_BODY, &self->mainAnimator, true, 0);
1227
1228
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
1229
1230
if (showGizmos()) {
1231
RSDK_DRAWING_OVERLAY(true);
1232
1233
DrawHelpers_DrawArenaBounds(-WIDE_SCR_XCENTER + 32, -SCREEN_YSIZE + 16, WIDE_SCR_XCENTER + 32, 16, 1 | 2 | 4 | 8, 0x00C0F0);
1234
1235
RSDK_DRAWING_OVERLAY(false);
1236
}
1237
break;
1238
1239
case GIGAMETAL_COVER:
1240
self->inkEffect = INK_ADD;
1241
self->alpha = 0xFF;
1242
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_COVER, &self->mainAnimator, true, 0);
1243
1244
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
1245
break;
1246
1247
case GIGAMETAL_ARMFRONT:
1248
self->componentPos.x = -0x1C0000;
1249
self->componentPos.y = -0x2C0000;
1250
self->drawGroup = Zone->objectDrawGroup[1];
1251
1252
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_ARMFRONT, &self->mainAnimator, true, 0);
1253
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_ARMFRONT, &self->jointAnimator, true, 1);
1254
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_ARMFRONT, &self->armAnimator, true, 2);
1255
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_ARMFRONT, &self->handAnimator, true, 3);
1256
1257
self->body = self;
1258
GigaMetal_Draw_Arm();
1259
break;
1260
1261
case GIGAMETAL_ARMBACK:
1262
self->componentPos.x = -0xC0000;
1263
self->componentPos.y = -0x2C0000;
1264
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_ARMBACK, &self->mainAnimator, true, 0);
1265
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_ARMBACK, &self->jointAnimator, true, 1);
1266
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_ARMBACK, &self->armAnimator, true, 2);
1267
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_ARMBACK, &self->handAnimator, true, 3);
1268
1269
self->body = self;
1270
GigaMetal_Draw_Arm();
1271
break;
1272
1273
case GIGAMETAL_LASEREDGE:
1274
self->drawFX = FX_ROTATE;
1275
self->laserSize = -1;
1276
self->angle = 0x40;
1277
self->visible = true;
1278
self->scale.x = 0x200;
1279
self->scale.y = 0x200;
1280
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_LASEREDGE, &self->mainAnimator, true, 0);
1281
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_LASERBEAM, &self->jointAnimator, true, 0);
1282
RSDK.SetSpriteAnimation(GigaMetal->aniFrames, GIGAMETAL_LASEREDGE, &self->armAnimator, true, 1);
1283
1284
self->body = self;
1285
GigaMetal_Draw_LaserEdge();
1286
break;
1287
1288
case GIGAMETAL_SHARD: break;
1289
1290
default: break;
1291
}
1292
}
1293
1294
void GigaMetal_EditorLoad(void)
1295
{
1296
GigaMetal->aniFrames = RSDK.LoadSpriteAnimation("SSZ2/GigaMetal.bin", SCOPE_STAGE);
1297
1298
RSDK_ACTIVE_VAR(GigaMetal, aniID);
1299
RSDK_ENUM_VAR("Head", GIGAMETAL_HEAD);
1300
RSDK_ENUM_VAR("Shoulder", GIGAMETAL_SHOULDER);
1301
RSDK_ENUM_VAR("Body", GIGAMETAL_BODY);
1302
RSDK_ENUM_VAR("Cover", GIGAMETAL_COVER);
1303
RSDK_ENUM_VAR("Eye", GIGAMETAL_EYE);
1304
RSDK_ENUM_VAR("Arm (Front)", GIGAMETAL_ARMFRONT);
1305
RSDK_ENUM_VAR("Arm (Back)", GIGAMETAL_ARMBACK);
1306
}
1307
#endif
1308
1309
void GigaMetal_Serialize(void)
1310
{
1311
RSDK_EDITABLE_VAR(GigaMetal, VAR_UINT8, aniID);
1312
RSDK_EDITABLE_VAR(GigaMetal, VAR_UINT8, frameID);
1313
}
1314
#endif
1315
1316