Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/SSZ/HotaruHiWatt.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: HotaruHiWatt Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectHotaruHiWatt *HotaruHiWatt;
11
12
void HotaruHiWatt_Update(void)
13
{
14
RSDK_THIS(HotaruHiWatt);
15
16
if (self->invincibilityTimer > 0)
17
self->invincibilityTimer--;
18
19
StateMachine_Run(self->state);
20
}
21
22
void HotaruHiWatt_LateUpdate(void) {}
23
24
void HotaruHiWatt_StaticUpdate(void) {}
25
26
void HotaruHiWatt_Draw(void)
27
{
28
RSDK_THIS(HotaruHiWatt);
29
30
if (self->stateDraw) {
31
StateMachine_Run(self->stateDraw);
32
}
33
else {
34
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
35
}
36
}
37
38
void HotaruHiWatt_Create(void *data)
39
{
40
RSDK_THIS(HotaruHiWatt);
41
42
if (!SceneInfo->inEditor) {
43
if (globals->gameMode < MODE_TIMEATTACK) {
44
self->active = ACTIVE_XBOUNDS;
45
self->updateRange.x = 0xC00000;
46
self->updateRange.y = 0xC00000;
47
self->type = VOID_TO_INT(data);
48
self->drawGroup = Zone->objectDrawGroup[0];
49
50
switch (self->type) {
51
case HHW_BOSS:
52
self->visible = false;
53
self->drawFX = FX_FLIP;
54
self->health = 6;
55
RSDK.SetSpriteAnimation(HotaruHiWatt->aniFrames, 0, &self->headAnimator, true, 0);
56
RSDK.SetSpriteAnimation(HotaruHiWatt->aniFrames, 1, &self->bulbAnimator, true, 0);
57
58
self->alpha = 0x100;
59
self->state = HotaruHiWatt_StateBoss_SetupArena;
60
self->hitbox.left = -24;
61
self->hitbox.top = -24;
62
self->hitbox.right = 24;
63
self->hitbox.bottom = 24;
64
break;
65
66
case HHW_SINGLE_HOTARU:
67
RSDK.SetSpriteAnimation(HotaruHiWatt->hotaruFrames, 1, &self->mainAnimator, true, 3);
68
++self->drawGroup;
69
70
self->inkEffect = INK_ADD;
71
self->visible = true;
72
self->health = 3;
73
self->position.x += RSDK.Rand(-0x500000, 0x500000);
74
self->position.y += RSDK.Rand(-0x800000, 0x800000);
75
self->state = HotaruHiWatt_StateHotaru_DimScreen;
76
self->hitbox.left = -6;
77
self->hitbox.top = -6;
78
self->hitbox.right = 6;
79
self->hitbox.bottom = 6;
80
break;
81
82
case HHW_PAIR_HOTARU:
83
RSDK.SetSpriteAnimation(HotaruHiWatt->hotaruFrames, 1, &self->mainAnimator, true, 3);
84
85
self->originPos = self->position;
86
self->inkEffect = INK_ADD;
87
self->visible = true;
88
self->health = 3;
89
self->formationCircleRadius = 0x800;
90
self->alpha = -0x200;
91
self->state = HotaruHiWatt_StateHotaruPair_DimScreen;
92
self->hitbox.left = -6;
93
self->hitbox.top = -6;
94
self->hitbox.right = 6;
95
self->hitbox.bottom = 6;
96
break;
97
98
case HHW_SMALL_HOTARU:
99
RSDK.SetSpriteAnimation(HotaruHiWatt->hotaruFrames, 1, &self->mainAnimator, true, 3);
100
101
self->targetPos = self->position;
102
self->inkEffect = INK_ADD;
103
self->visible = true;
104
self->health = 3;
105
self->alpha = 0x100;
106
self->state = HotaruHiWatt_StateHotaru_MoveToTarget;
107
break;
108
109
case HHW_FLASH:
110
RSDK.SetSpriteAnimation(HotaruHiWatt->hotaruFrames, 1, &self->mainAnimator, true, 0);
111
112
self->inkEffect = INK_ADD;
113
self->visible = true;
114
self->health = 3;
115
self->alpha = 0x100;
116
self->state = HotaruHiWatt_StateBoss_FlashFadeOut;
117
break;
118
119
case HHW_UNUSED2: break;
120
121
case HHW_MINILASER:
122
RSDK.SetSpriteAnimation(HotaruHiWatt->hotaruFrames, 2, &self->mainAnimator, true, 1);
123
self->state = HotaruHiWatt_State_MiniLaser;
124
self->visible = true;
125
self->hitbox.left = -4;
126
self->hitbox.top = -8;
127
self->hitbox.right = 4;
128
self->hitbox.bottom = 8;
129
break;
130
131
case HHW_ELECTRICORB:
132
RSDK.SetSpriteAnimation(HotaruHiWatt->hotaruFrames, 4, &self->mainAnimator, true, 0);
133
self->state = HotaruHiWatt_State_SparkyOrb;
134
self->visible = true;
135
self->hitbox.left = -8;
136
self->hitbox.top = -8;
137
self->hitbox.right = 8;
138
self->hitbox.bottom = 8;
139
break;
140
141
default: break;
142
}
143
}
144
else {
145
destroyEntity(self);
146
}
147
}
148
}
149
150
void HotaruHiWatt_StageLoad(void)
151
{
152
HotaruHiWatt->aniFrames = RSDK.LoadSpriteAnimation("SSZ1/HotaruHiWatt.bin", SCOPE_STAGE);
153
HotaruHiWatt->hotaruFrames = RSDK.LoadSpriteAnimation("SSZ1/HotaruMKII.bin", SCOPE_STAGE);
154
155
HotaruHiWatt->spawnedLaserStrike = false;
156
RSDK.CopyPalette(1, 128, 0, 128, 64);
157
158
HotaruHiWatt->sfxHit = RSDK.GetSfx("Stage/BossHit.wav");
159
HotaruHiWatt->sfxExplosion = RSDK.GetSfx("Stage/Explosion2.wav");
160
HotaruHiWatt->sfxHHWAppear = RSDK.GetSfx("SSZ1/HHWAppear.wav");
161
HotaruHiWatt->sfxFlash = RSDK.GetSfx("SSZ1/HHWFlash.wav");
162
HotaruHiWatt->sfxLaser = RSDK.GetSfx("SSZ1/HotaruLaser.wav");
163
HotaruHiWatt->sfxAppear = RSDK.GetSfx("SSZ1/HotaruAppear.wav");
164
HotaruHiWatt->sfxFly = RSDK.GetSfx("SSZ1/HotaruFly.wav");
165
HotaruHiWatt->sfxFlyUp = RSDK.GetSfx("SSZ1/HHWFlyUp.wav");
166
HotaruHiWatt->sfxCharge = RSDK.GetSfx("SSZ1/HHWCharge.wav");
167
168
Soundboard_LoadSfx("Stage/Zap.wav", true, HotaruHiWatt_SfxCheck_Zap, StateMachine_None);
169
Soundboard_LoadSfx("SSZ1/HHWLaser.wav", 32606, HotaruHiWatt_SfxCheck_HHWLaser, HotaruHiWatt_SfxUpdate_HHWLaser);
170
}
171
172
bool32 HotaruHiWatt_SfxCheck_Zap(void)
173
{
174
int32 count = 0;
175
foreach_active(HotaruHiWatt, boss)
176
{
177
if (boss->state == HotaruHiWatt_StateHotaruPair_AttackDelay || boss->state == HotaruHiWatt_StateHotaruPair_AttackMovingDown
178
|| boss->state == HotaruHiWatt_StateHotaruPair_AttackMovingUp)
179
++count;
180
}
181
return count > 1;
182
}
183
184
bool32 HotaruHiWatt_SfxCheck_HHWLaser(void)
185
{
186
int32 count = 0;
187
foreach_active(HotaruHiWatt, boss)
188
{
189
if (boss->state == HotaruHiWatt_StateBoss_LaserAttack_Right || boss->state == HotaruHiWatt_StateBoss_LaserAttack_Left)
190
++count;
191
}
192
return count > 0;
193
}
194
195
void HotaruHiWatt_SfxUpdate_HHWLaser(int32 sfx)
196
{
197
if (!(Soundboard->sfxPlayingTimer[sfx] % 6))
198
Camera_ShakeScreen(0, 0, 2);
199
}
200
201
void HotaruHiWatt_Hit(void)
202
{
203
RSDK_THIS(HotaruHiWatt);
204
205
if (--self->health <= 0) {
206
self->stateDraw = HotaruHiWatt_Draw_Boss;
207
self->state = HotaruHiWatt_StateBoss_Destroyed;
208
self->timer = 0;
209
SceneInfo->timeEnabled = false;
210
Player_GiveScore(RSDK_GET_ENTITY(SLOT_PLAYER1, Player), 1000);
211
}
212
else {
213
self->invincibilityTimer = 48;
214
RSDK.PlaySfx(HotaruHiWatt->sfxHit, false, 255);
215
}
216
}
217
218
void HotaruHiWatt_Explode(void)
219
{
220
RSDK_THIS(HotaruHiWatt);
221
222
if (!(Zone->timer % 3)) {
223
RSDK.PlaySfx(HotaruHiWatt->sfxExplosion, false, 255);
224
225
if (Zone->timer & 4) {
226
int32 x = self->position.x + (RSDK.Rand(self->hitbox.left, self->hitbox.right) << 16);
227
int32 y = self->position.y + (RSDK.Rand(self->hitbox.top, self->hitbox.bottom) << 16);
228
CREATE_ENTITY(Explosion, INT_TO_VOID((RSDK.Rand(0, 256) > 192) + EXPLOSION_BOSS), x, y)->drawGroup = Zone->objectDrawGroup[1];
229
}
230
}
231
}
232
233
void HotaruHiWatt_CheckPlayerCollisions_Hotaru(void)
234
{
235
RSDK_THIS(HotaruHiWatt);
236
237
foreach_active(Player, player)
238
{
239
if (Player_CheckBadnikTouch(player, self, &self->hitbox) && Player_CheckBadnikBreak(player, self, false)) {
240
if (self->type == HHW_SINGLE_HOTARU) {
241
HotaruHiWatt_SpawnPairHotarus();
242
}
243
else {
244
int32 hotaruPairCount = 0;
245
foreach_active(HotaruHiWatt, boss)
246
{
247
if (boss->type == HHW_PAIR_HOTARU)
248
hotaruPairCount++;
249
}
250
251
if (hotaruPairCount == 1)
252
HotaruHiWatt_SetupHHWReappear();
253
}
254
255
destroyEntity(self);
256
}
257
}
258
}
259
260
void HotaruHiWatt_CheckPlayerCollisions_Boss(void)
261
{
262
RSDK_THIS(HotaruHiWatt);
263
264
foreach_active(Player, player)
265
{
266
if (!self->invincibilityTimer && Player_CheckBadnikTouch(player, self, &self->hitbox) && Player_CheckBossHit(player, self))
267
HotaruHiWatt_Hit();
268
}
269
}
270
271
void HotaruHiWatt_CheckPlayerCollisions_MiniLaser(void)
272
{
273
RSDK_THIS(HotaruHiWatt);
274
275
foreach_active(Player, player)
276
{
277
if (!self->invincibilityTimer) {
278
if (Player_CheckCollisionTouch(player, self, &self->hitbox))
279
Player_Hurt(player, self);
280
}
281
}
282
}
283
284
void HotaruHiWatt_CheckPlayerCollisions_BossLaser(void)
285
{
286
RSDK_THIS(HotaruHiWatt);
287
288
foreach_active(Player, player)
289
{
290
Hitbox hitbox = self->hitbox;
291
if (!player->invincibleTimer && !player->blinkTimer)
292
hitbox.bottom += 0x80;
293
294
if (Player_CheckBadnikTouch(player, self, &hitbox)) {
295
if (self->invincibilityTimer) {
296
if (player->position.y > self->position.y)
297
Player_Hurt(player, self);
298
}
299
else if (player->position.y < self->position.y || player->invincibleTimer || player->blinkTimer) {
300
if (Player_CheckBossHit(player, self))
301
HotaruHiWatt_Hit();
302
}
303
else {
304
Player_Hurt(player, self);
305
}
306
}
307
}
308
}
309
310
void HotaruHiWatt_Draw_Hotaru(void)
311
{
312
RSDK_THIS(HotaruHiWatt);
313
314
self->inkEffect = INK_ADD;
315
316
if (!(self->timer & 2))
317
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
318
319
int32 alpha = self->alpha;
320
self->alpha = self->bulbAlpha;
321
RSDK.DrawSprite(&self->bulbAnimator, NULL, false);
322
323
self->alpha = alpha;
324
}
325
326
void HotaruHiWatt_Draw_HotaruAttacking(void)
327
{
328
RSDK_THIS(HotaruHiWatt);
329
330
self->inkEffect = INK_NONE;
331
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
332
333
self->inkEffect = INK_ADD;
334
RSDK.DrawSprite(&self->bulbAnimator, NULL, false);
335
}
336
337
void HotaruHiWatt_Draw_Boss(void)
338
{
339
RSDK_THIS(HotaruHiWatt);
340
341
if (RSDK.GetFrameID(&self->headAnimator) == 'b')
342
self->direction = FLIP_X;
343
344
if (self->invincibilityTimer & 1) {
345
RSDK.CopyPalette(2, 240, 0, 240, 16);
346
347
RSDK.DrawSprite(&self->headAnimator, NULL, false);
348
349
self->direction = FLIP_NONE;
350
RSDK.DrawSprite(&self->bulbAnimator, NULL, false);
351
352
RSDK.CopyPalette(1, 240, 0, 240, 16);
353
}
354
else {
355
RSDK.DrawSprite(&self->headAnimator, NULL, false);
356
357
self->direction = FLIP_NONE;
358
RSDK.DrawSprite(&self->bulbAnimator, NULL, false);
359
}
360
}
361
362
void HotaruHiWatt_Draw_BossLaserCharging(void)
363
{
364
RSDK_THIS(HotaruHiWatt);
365
366
if (RSDK.GetFrameID(&self->headAnimator) == 'b')
367
self->direction = FLIP_X;
368
369
if (self->invincibilityTimer & 1) {
370
RSDK.CopyPalette(2, 240, 0, 240, 16);
371
RSDK.DrawSprite(&self->headAnimator, NULL, false);
372
373
self->direction = FLIP_NONE;
374
RSDK.DrawSprite(&self->bulbAnimator, NULL, false);
375
376
RSDK.CopyPalette(1, 240, 0, 240, 16);
377
}
378
else {
379
RSDK.DrawSprite(&self->headAnimator, NULL, false);
380
381
self->direction = FLIP_NONE;
382
RSDK.DrawSprite(&self->bulbAnimator, NULL, false);
383
}
384
385
self->inkEffect = INK_ADD;
386
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
387
388
self->inkEffect = INK_ALPHA;
389
RSDK.DrawSprite(&self->bulbFlashAnimator, NULL, false);
390
391
self->inkEffect = INK_NONE;
392
}
393
394
void HotaruHiWatt_Draw_BossLaser(void)
395
{
396
RSDK_THIS(HotaruHiWatt);
397
398
Vector2 drawPos;
399
if (RSDK.GetFrameID(&self->headAnimator) == 'b')
400
self->direction = FLIP_X;
401
402
if (self->invincibilityTimer & 1) {
403
RSDK.CopyPalette(2, 240, 0, 240, 16);
404
RSDK.DrawSprite(&self->headAnimator, NULL, false);
405
406
self->direction = FLIP_NONE;
407
RSDK.DrawSprite(&self->bulbAnimator, NULL, false);
408
409
RSDK.CopyPalette(1, 240, 0, 240, 16);
410
}
411
else {
412
RSDK.DrawSprite(&self->headAnimator, NULL, false);
413
414
self->direction = FLIP_NONE;
415
RSDK.DrawSprite(&self->bulbAnimator, NULL, false);
416
}
417
418
self->inkEffect = INK_ALPHA;
419
self->bulbFlashAnimator.frameID = 0;
420
RSDK.DrawSprite(&self->bulbFlashAnimator, NULL, false);
421
422
self->bulbFlashAnimator.frameID = 1;
423
RSDK.DrawSprite(&self->bulbFlashAnimator, NULL, false);
424
425
drawPos = self->position;
426
drawPos.y += 0x180000 + ((Zone->timer & 7) << 20);
427
self->direction = (Zone->timer >> 2) & 1;
428
RSDK.DrawSprite(&self->mainAnimator, &drawPos, false);
429
430
self->direction = FLIP_NONE;
431
RSDK.DrawSprite(&self->laserImpactAnimator, &self->laserImpactPos, false);
432
433
self->inkEffect = INK_NONE;
434
}
435
436
void HotaruHiWatt_Draw_FormingHHW(void)
437
{
438
RSDK_THIS(HotaruHiWatt);
439
440
RSDK.DrawCircle(self->position.x, self->position.y, self->formationCircleRadius >> 16, 0xF0F0F0, 128, INK_ADD, false);
441
RSDK.DrawCircle(self->position.x, self->position.y, self->formationCircleRadius / 0xCCCC, 0xF0F0F0, 128, INK_ADD, false);
442
}
443
444
void HotaruHiWatt_Draw_FlashAppear(void)
445
{
446
RSDK_THIS(HotaruHiWatt);
447
448
if (RSDK.GetFrameID(&self->headAnimator) == 'b')
449
self->direction = FLIP_X;
450
451
RSDK.DrawSprite(&self->headAnimator, NULL, false);
452
453
self->direction = FLIP_NONE;
454
RSDK.DrawSprite(&self->bulbAnimator, NULL, false);
455
456
RSDK.DrawCircle(self->position.x, self->position.y, self->formationCircleRadius >> 16, 0xF0F0F0, self->alpha >> 1, INK_ADD, false);
457
RSDK.DrawCircle(self->position.x, self->position.y, self->formationCircleRadius / 0xCCCC, 0xF0F0F0, self->alpha >> 1, INK_ADD, false);
458
}
459
460
void HotaruHiWatt_SpawnPairHotarus(void)
461
{
462
RSDK_THIS(HotaruHiWatt);
463
464
EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
465
466
EntityHotaruHiWatt *boss = self->parents[0];
467
468
if (boss->state != HotaruHiWatt_StateBoss_HiddenDimScreen)
469
boss->state = HotaruHiWatt_StateBoss_HiddenDimScreen;
470
471
EntityHotaruHiWatt *pairHotaru1 = CREATE_ENTITY(HotaruHiWatt, INT_TO_VOID(HHW_PAIR_HOTARU), player1->position.x, HotaruHiWatt->startY + 0x200000);
472
pairHotaru1->isPermanent = true;
473
pairHotaru1->parents[0] = boss;
474
475
EntityHotaruHiWatt *pairHotaru2 = CREATE_ENTITY(HotaruHiWatt, INT_TO_VOID(HHW_PAIR_HOTARU), player1->position.x, HotaruHiWatt->startY + 0x200000);
476
pairHotaru2->angle += 0x800000;
477
pairHotaru2->isPermanent = true;
478
pairHotaru2->parents[0] = boss;
479
pairHotaru1->parents[1] = pairHotaru2;
480
}
481
482
void HotaruHiWatt_SetupHHWReappear(void)
483
{
484
RSDK_THIS(HotaruHiWatt);
485
486
EntityHotaruHiWatt *boss = self->parents[0];
487
488
if (RSDK_GET_ENTITY(SLOT_PLAYER1, Player)->position.x <= HotaruHiWatt->boundsM)
489
boss->position.x = HotaruHiWatt->boundsR;
490
else
491
boss->position.x = HotaruHiWatt->boundsL;
492
493
boss->position.y = HotaruHiWatt->startY;
494
495
boss->nextState = HotaruHiWatt_StateBoss_LaserAttackDelay;
496
boss->state = HotaruHiWatt_StateBoss_DimScreen;
497
}
498
499
void HotaruHiWatt_StateBoss_SetupArena(void)
500
{
501
RSDK_THIS(HotaruHiWatt);
502
503
if (++self->timer >= 8) {
504
self->timer = 0;
505
506
Zone->playerBoundActiveL[0] = true;
507
Zone->playerBoundActiveR[0] = true;
508
509
Zone->cameraBoundsL[0] = (self->position.x >> 16) - ScreenInfo->center.x;
510
Zone->cameraBoundsR[0] = (self->position.x >> 16) + ScreenInfo->center.x;
511
Zone->cameraBoundsT[0] = (self->position.y >> 16) - ScreenInfo->size.y;
512
Zone->cameraBoundsB[0] = (self->position.y >> 16);
513
514
HotaruHiWatt->boundsL = (Zone->cameraBoundsL[0] + 64) << 16;
515
HotaruHiWatt->boundsR = (Zone->cameraBoundsR[0] - 64) << 16;
516
HotaruHiWatt->boundsM = self->position.x;
517
HotaruHiWatt->boundsT = (Zone->cameraBoundsT[0] + 48) << 16;
518
HotaruHiWatt->boundsB = (Zone->cameraBoundsB[0] - 8) << 16;
519
520
foreach_active(Fireflies, fireflies)
521
{
522
if (fireflies->state == Fireflies_State_Spawner)
523
destroyEntity(fireflies);
524
}
525
526
self->state = HotaruHiWatt_StateBoss_AwaitPlayer;
527
}
528
}
529
530
void HotaruHiWatt_StateBoss_AwaitPlayer(void)
531
{
532
RSDK_THIS(HotaruHiWatt);
533
534
if (RSDK_GET_ENTITY(SLOT_PLAYER1, Player)->position.x > self->position.x) {
535
self->position.y += -0x100000 - (ScreenInfo->center.y << 16);
536
HotaruHiWatt->startY = self->position.y;
537
538
self->state = HotaruHiWatt_StateBoss_DimScreen;
539
self->nextState = HotaruHiWatt_StateBoss_Appear;
540
}
541
}
542
543
void HotaruHiWatt_StateBoss_Appear(void)
544
{
545
RSDK_THIS(HotaruHiWatt);
546
547
RSDK.ProcessAnimation(&self->headAnimator);
548
549
self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);
550
551
if (++self->timer == 60) {
552
self->timer = 0;
553
RSDK.PlaySfx(HotaruHiWatt->sfxFlyUp, false, 255);
554
self->state = HotaruHiWatt_StateBoss_FlyUp;
555
}
556
557
HotaruHiWatt_CheckPlayerCollisions_Boss();
558
}
559
560
void HotaruHiWatt_StateBoss_FlyUp(void)
561
{
562
RSDK_THIS(HotaruHiWatt);
563
564
self->velocity.y -= 0x3800;
565
self->originPos.y += self->velocity.y;
566
567
RSDK.ProcessAnimation(&self->headAnimator);
568
569
self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);
570
571
HotaruHiWatt_CheckPlayerCollisions_Boss();
572
573
if (!RSDK.CheckOnScreen(self, NULL)) {
574
self->position.x = HotaruHiWatt->boundsM;
575
self->position.y = HotaruHiWatt->startY;
576
self->state = self->nextState;
577
self->visible = false;
578
579
EntityHotaruHiWatt *hotaru = CREATE_ENTITY(HotaruHiWatt, INT_TO_VOID(HHW_SINGLE_HOTARU), self->position.x, self->position.y);
580
hotaru->isPermanent = true;
581
hotaru->parents[0] = self;
582
}
583
}
584
585
void HotaruHiWatt_StateHotaru_MoveToTarget(void)
586
{
587
RSDK_THIS(HotaruHiWatt);
588
589
self->position.x += self->velocity.x;
590
self->position.y += self->velocity.y;
591
592
if (!(Zone->timer & 3))
593
CREATE_ENTITY(HotaruHiWatt, INT_TO_VOID(HHW_FLASH), self->position.x, self->position.y);
594
595
if (!((self->position.x ^ self->targetPos.x) & 0xFFF80000)) {
596
if (!((self->position.y ^ self->targetPos.y) & 0xFFF80000)) {
597
self->position.x = self->targetPos.x;
598
self->position.y = self->targetPos.y;
599
self->velocity.x = 0;
600
self->velocity.y = 0;
601
602
if (!self->nextState) {
603
destroyEntity(self);
604
}
605
else {
606
RSDK.PlaySfx(HotaruHiWatt->sfxAppear, false, 0xFF);
607
self->state = self->nextState;
608
}
609
}
610
}
611
}
612
613
void HotaruHiWatt_StateBoss_FlashFadeOut(void)
614
{
615
RSDK_THIS(HotaruHiWatt);
616
617
RSDK.ProcessAnimation(&self->mainAnimator);
618
619
self->alpha -= 8;
620
if (self->alpha <= 0)
621
destroyEntity(self);
622
}
623
624
void HotaruHiWatt_StateBoss_HiddenDimScreen(void)
625
{
626
RSDK_THIS(HotaruHiWatt);
627
628
if (self->timer >= 192)
629
self->state = StateMachine_None;
630
else
631
self->timer += 8;
632
633
RSDK.SetLimitedFade(0, 1, 2, self->timer, 128, 192);
634
}
635
636
void HotaruHiWatt_StateBoss_HiddenUndimScreen(void)
637
{
638
RSDK_THIS(HotaruHiWatt);
639
640
if (self->timer <= 0)
641
self->state = StateMachine_None;
642
else
643
self->timer -= 8;
644
645
RSDK.SetLimitedFade(0, 1, 2, self->timer, 128, 192);
646
}
647
648
void HotaruHiWatt_StateHotaru_DimScreen(void)
649
{
650
RSDK_THIS(HotaruHiWatt);
651
652
EntityHotaruHiWatt *boss = self->parents[0];
653
654
if (boss->state != HotaruHiWatt_StateBoss_HiddenDimScreen)
655
boss->state = HotaruHiWatt_StateBoss_HiddenDimScreen;
656
657
if (self->bulbAlpha >= 256) {
658
self->targetPos.x = HotaruHiWatt->boundsM + RSDK.Rand(-0x800000, 0x800000);
659
self->targetPos.y = HotaruHiWatt->startY + RSDK.Rand(-0x500000, 0x500000);
660
self->stateDraw = HotaruHiWatt_Draw_Hotaru;
661
self->velocity.x = (self->targetPos.x - self->position.x) / 48;
662
self->velocity.y = (self->targetPos.y - self->position.y) / 48;
663
664
RSDK.PlaySfx(HotaruHiWatt->sfxFly, false, 255);
665
666
self->nextState = HotaruHiWatt_StateHotaru_Charging;
667
self->state = HotaruHiWatt_StateHotaru_MoveToTarget;
668
}
669
else {
670
self->bulbAlpha += 16;
671
}
672
}
673
674
void HotaruHiWatt_StateHotaru_Charging(void)
675
{
676
RSDK_THIS(HotaruHiWatt);
677
678
EntityHotaruHiWatt *boss = self->parents[0];
679
680
if (boss->state != HotaruHiWatt_StateBoss_HiddenUndimScreen)
681
boss->state = HotaruHiWatt_StateBoss_HiddenUndimScreen;
682
683
RSDK.ProcessAnimation(&self->bulbAnimator);
684
685
if (!self->timer) {
686
RSDK.SetSpriteAnimation(HotaruHiWatt->hotaruFrames, 0, &self->mainAnimator, true, 0);
687
RSDK.SetSpriteAnimation(HotaruHiWatt->hotaruFrames, 1, &self->bulbAnimator, true, 0);
688
}
689
690
self->alpha = 8 * ++self->timer;
691
692
if (self->timer == 32) {
693
self->timer = 0;
694
self->state = HotaruHiWatt_StateHotaru_Attacking;
695
self->stateDraw = HotaruHiWatt_Draw_HotaruAttacking;
696
697
RSDK.PlaySfx(HotaruHiWatt->sfxLaser, false, 255);
698
}
699
700
HotaruHiWatt_CheckPlayerCollisions_Hotaru();
701
}
702
703
void HotaruHiWatt_StateHotaru_Attacking(void)
704
{
705
RSDK_THIS(HotaruHiWatt);
706
707
RSDK.ProcessAnimation(&self->bulbAnimator);
708
709
++self->timer;
710
if (!(self->timer & 1))
711
CREATE_ENTITY(HotaruHiWatt, INT_TO_VOID(HHW_MINILASER), self->position.x, self->position.y + 0x40000);
712
713
if (self->timer == 24) {
714
self->timer = 0;
715
self->stateDraw = HotaruHiWatt_Draw_Hotaru;
716
self->state = HotaruHiWatt_StateHotaru_FinishedAttack;
717
}
718
719
HotaruHiWatt_CheckPlayerCollisions_Hotaru();
720
}
721
722
void HotaruHiWatt_StateHotaru_FinishedAttack(void)
723
{
724
RSDK_THIS(HotaruHiWatt);
725
726
EntityHotaruHiWatt *boss = self->parents[0];
727
728
if (boss->state != HotaruHiWatt_StateBoss_HiddenDimScreen)
729
boss->state = HotaruHiWatt_StateBoss_HiddenDimScreen;
730
731
++self->timer;
732
733
if (self->alpha <= 0) {
734
// health prolly should be named "remainingAttacks" here
735
if (self->health >= 1) {
736
self->timer = 0;
737
self->health--;
738
RSDK.SetSpriteAnimation(HotaruHiWatt->hotaruFrames, 1, &self->mainAnimator, true, 3);
739
self->stateDraw = StateMachine_None;
740
self->state = HotaruHiWatt_StateHotaru_DimScreen;
741
}
742
else {
743
self->state = HotaruHiWatt_StateHotaru_EndAttackSequence;
744
}
745
}
746
else {
747
self->alpha -= 8;
748
}
749
750
HotaruHiWatt_CheckPlayerCollisions_Hotaru();
751
}
752
753
void HotaruHiWatt_StateHotaru_EndAttackSequence(void)
754
{
755
RSDK_THIS(HotaruHiWatt);
756
757
if (self->bulbAlpha <= 0) {
758
HotaruHiWatt_SpawnPairHotarus();
759
destroyEntity(self);
760
}
761
else {
762
self->bulbAlpha -= 32;
763
HotaruHiWatt_CheckPlayerCollisions_Hotaru();
764
}
765
}
766
767
void HotaruHiWatt_State_MiniLaser(void)
768
{
769
RSDK_THIS(HotaruHiWatt);
770
771
self->position.y += 0x80000;
772
773
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x80000, true)) {
774
if (HotaruHiWatt->spawnedLaserStrike) {
775
destroyEntity(self);
776
}
777
else {
778
RSDK.SetSpriteAnimation(HotaruHiWatt->hotaruFrames, 3, &self->mainAnimator, true, 0);
779
self->position.y += 0x80000;
780
self->drawGroup = Zone->objectDrawGroup[1];
781
self->state = HotaruHiWatt_State_MiniLaserStrike;
782
HotaruHiWatt->spawnedLaserStrike = true;
783
}
784
}
785
786
if (self->classID == HotaruHiWatt->classID)
787
HotaruHiWatt_CheckPlayerCollisions_MiniLaser();
788
}
789
790
void HotaruHiWatt_State_MiniLaserStrike(void)
791
{
792
RSDK_THIS(HotaruHiWatt);
793
794
RSDK.ProcessAnimation(&self->mainAnimator);
795
796
if (self->mainAnimator.frameID == 2)
797
HotaruHiWatt->spawnedLaserStrike = false;
798
799
if (self->mainAnimator.frameID == self->mainAnimator.frameCount - 1)
800
destroyEntity(self);
801
}
802
803
void HotaruHiWatt_StateHotaruPair_DimScreen(void)
804
{
805
RSDK_THIS(HotaruHiWatt);
806
807
EntityHotaruHiWatt *boss = self->parents[0];
808
809
if (boss->state != HotaruHiWatt_StateBoss_HiddenDimScreen)
810
boss->state = HotaruHiWatt_StateBoss_HiddenDimScreen;
811
812
self->position.x = self->formationCircleRadius * RSDK.Cos1024(self->angle >> 14) + self->originPos.x;
813
self->position.y = self->formationCircleRadius * RSDK.Sin1024(self->angle >> 14) + self->originPos.y;
814
815
if (self->alpha >= 0x100)
816
self->state = HotaruHiWatt_StateHotaruPair_PrepareAttack;
817
else
818
self->alpha += 0x10;
819
}
820
821
void HotaruHiWatt_StateHotaruPair_PrepareAttack(void)
822
{
823
RSDK_THIS(HotaruHiWatt);
824
825
if (self->timer >= 64) {
826
if (self->velocity.x > 0)
827
self->velocity.x -= 0x2000;
828
}
829
else {
830
if (self->velocity.x < 0x80000)
831
self->velocity.x += 0x2000;
832
}
833
834
if (self->originPos.x < HotaruHiWatt->boundsM - 0x600000)
835
self->originPos.x += 0x20000;
836
else if (self->originPos.x > HotaruHiWatt->boundsM + 0x600000)
837
self->originPos.x -= 0x20000;
838
839
self->originPos.y -= self->velocity.x >> 2;
840
self->formationCircleRadius += self->velocity.x >> 13;
841
842
if (!(self->timer % 30) && self->timer < 120)
843
RSDK.PlaySfx(HotaruHiWatt->sfxFly, (self->timer % 30), 0xFF);
844
845
self->angle += self->velocity.x;
846
847
++self->timer;
848
self->position.x = self->formationCircleRadius * RSDK.Cos1024(self->angle >> 14) + self->originPos.x;
849
self->position.y = self->formationCircleRadius * RSDK.Sin1024(self->angle >> 14) + self->originPos.y;
850
851
if (!(Zone->timer & 3))
852
CREATE_ENTITY(HotaruHiWatt, INT_TO_VOID(HHW_FLASH), self->position.x, self->position.y);
853
854
if (self->timer == 128) {
855
self->timer = 0;
856
RSDK.PlaySfx(HotaruHiWatt->sfxAppear, false, 255);
857
self->state = HotaruHiWatt_StateHotaruPair_Charging;
858
}
859
}
860
861
void HotaruHiWatt_StateHotaruPair_Charging(void)
862
{
863
RSDK_THIS(HotaruHiWatt);
864
865
EntityHotaruHiWatt *boss = self->parents[0];
866
867
if (boss->state != HotaruHiWatt_StateBoss_HiddenUndimScreen)
868
boss->state = HotaruHiWatt_StateBoss_HiddenUndimScreen;
869
870
RSDK.ProcessAnimation(&self->bulbAnimator);
871
872
if (!self->timer) {
873
RSDK.SetSpriteAnimation(HotaruHiWatt->hotaruFrames, 0, &self->mainAnimator, true, 0);
874
RSDK.SetSpriteAnimation(HotaruHiWatt->hotaruFrames, 1, &self->bulbAnimator, true, 0);
875
}
876
877
self->alpha = 8 * ++self->timer;
878
if (self->timer == 32) {
879
self->timer = 0;
880
self->velocity.y = 0;
881
882
self->stateDraw = HotaruHiWatt_Draw_HotaruAttacking;
883
self->state = HotaruHiWatt_StateHotaruPair_AttackDelay;
884
885
if (self->parents[1]) {
886
for (int32 i = 30; i < 254; i += 28) {
887
EntityHotaruHiWatt *orb = CREATE_ENTITY(HotaruHiWatt, INT_TO_VOID(HHW_ELECTRICORB), self->position.x, self->position.y);
888
orb->scale.x = i;
889
orb->angle = RSDK.Rand(0, 256);
890
orb->parents[1] = self;
891
orb->parents[2] = self->parents[1];
892
}
893
}
894
}
895
}
896
897
void HotaruHiWatt_StateHotaruPair_AttackDelay(void)
898
{
899
RSDK_THIS(HotaruHiWatt);
900
901
if (++self->timer == 32) {
902
self->timer = 0;
903
self->state = HotaruHiWatt_StateHotaruPair_AttackMovingDown;
904
}
905
}
906
907
void HotaruHiWatt_StateHotaruPair_AttackMovingDown(void)
908
{
909
RSDK_THIS(HotaruHiWatt);
910
911
RSDK.ProcessAnimation(&self->bulbAnimator);
912
913
self->velocity.y += 0x800;
914
915
if (self->velocity.y > 0x20000) {
916
self->velocity.y = 0x20000;
917
if (self->position.y > HotaruHiWatt->startY + 0x140000)
918
self->state = HotaruHiWatt_StateHotaruPair_AttackMovingUp;
919
}
920
921
self->position.y += self->velocity.y;
922
923
HotaruHiWatt_CheckPlayerCollisions_Hotaru();
924
}
925
926
void HotaruHiWatt_StateHotaruPair_AttackMovingUp(void)
927
{
928
RSDK_THIS(HotaruHiWatt);
929
930
RSDK.ProcessAnimation(&self->bulbAnimator);
931
932
self->velocity.y -= 0x1000;
933
if (self->velocity.y < -0x20000)
934
self->velocity.y = -0x20000;
935
936
self->position.y += self->velocity.y;
937
938
if (self->position.y < HotaruHiWatt->startY - 0xC00000) {
939
HotaruHiWatt_SetupHHWReappear();
940
destroyEntity(self);
941
}
942
943
HotaruHiWatt_CheckPlayerCollisions_Hotaru();
944
}
945
946
void HotaruHiWatt_State_SparkyOrb(void)
947
{
948
RSDK_THIS(HotaruHiWatt);
949
950
RSDK.ProcessAnimation(&self->mainAnimator);
951
952
EntityHotaruHiWatt *hotaruPair1 = self->parents[1];
953
EntityHotaruHiWatt *hotaruPair2 = self->parents[2];
954
955
if (hotaruPair1->classID == HotaruHiWatt->classID && hotaruPair2->classID == HotaruHiWatt->classID) {
956
int32 scale = (RSDK.Sin256(self->angle + 4 * Zone->timer) >> 7) + self->scale.x;
957
958
self->position.x = hotaruPair1->position.x + scale * ((hotaruPair2->position.x - hotaruPair1->position.x) >> 8);
959
self->position.y = hotaruPair1->position.y + 0xC0000 + scale * ((hotaruPair2->position.y - hotaruPair1->position.y) >> 8);
960
self->position.y += RSDK.Sin256(self->angle + 4 * Zone->timer) << 9;
961
962
HotaruHiWatt_CheckPlayerCollisions_MiniLaser();
963
}
964
else {
965
self->alpha = 0x100;
966
self->inkEffect = INK_ALPHA;
967
self->state = HotaruHiWatt_State_SparkyOrb_FadeOut;
968
969
self->velocity.x = RSDK.Rand(-0x20000, 0x20000);
970
self->velocity.y = RSDK.Rand(-0x20000, 0x20000);
971
}
972
}
973
974
void HotaruHiWatt_State_SparkyOrb_FadeOut(void)
975
{
976
RSDK_THIS(HotaruHiWatt);
977
978
RSDK.ProcessAnimation(&self->mainAnimator);
979
980
self->velocity.y += 0x3800;
981
self->position.x += self->velocity.x;
982
self->position.y += self->velocity.y;
983
984
if (self->alpha <= 0)
985
destroyEntity(self);
986
else
987
self->alpha -= 8;
988
}
989
990
void HotaruHiWatt_StateBoss_DimScreen(void)
991
{
992
RSDK_THIS(HotaruHiWatt);
993
994
EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
995
996
if (player1->onGround) {
997
if (self->timer >= 192) {
998
if (!self->playingBossTrack) {
999
Music_TransitionTrack(TRACK_MINIBOSS, 0.0125);
1000
self->playingBossTrack = true;
1001
}
1002
self->state = HotaruHiWatt_StateBoss_CreateSmallHHWs;
1003
RSDK.PlaySfx(HotaruHiWatt->sfxHHWAppear, false, 255);
1004
}
1005
else {
1006
self->timer += 8;
1007
}
1008
1009
RSDK.SetLimitedFade(0, 1, 2, self->timer, 128, 192);
1010
}
1011
}
1012
1013
void HotaruHiWatt_StateBoss_CreateSmallHHWs(void)
1014
{
1015
RSDK_THIS(HotaruHiWatt);
1016
1017
if (++self->timer == 224) {
1018
for (int32 angle = 0x20; angle < 0x120; angle += 0x40) {
1019
EntityHotaruHiWatt *hotaru = CREATE_ENTITY(HotaruHiWatt, INT_TO_VOID(HHW_SMALL_HOTARU), self->position.x, self->position.y - 0xC0000);
1020
hotaru->position.x += RSDK.Cos256(angle) << 16;
1021
hotaru->position.y += RSDK.Sin256(angle) << 16;
1022
hotaru->velocity.x = (hotaru->targetPos.x - hotaru->position.x) >> 6;
1023
hotaru->velocity.y = (hotaru->targetPos.y - hotaru->position.y) >> 6;
1024
}
1025
1026
self->timer = 0;
1027
self->velocity.x = 0x50000;
1028
self->stateDraw = HotaruHiWatt_Draw_FormingHHW;
1029
self->visible = true;
1030
self->state = HotaruHiWatt_StateBoss_FormingHHW;
1031
}
1032
}
1033
1034
void HotaruHiWatt_StateBoss_FormingHHW(void)
1035
{
1036
RSDK_THIS(HotaruHiWatt);
1037
1038
if (++self->timer >= 60) {
1039
self->velocity.x -= 0x3800;
1040
self->formationCircleRadius += self->velocity.x;
1041
1042
if (self->velocity.x <= 0) {
1043
self->originPos = self->position;
1044
self->timer = 192;
1045
self->stateDraw = HotaruHiWatt_Draw_FlashAppear;
1046
self->state = HotaruHiWatt_StateBoss_FlashAppear;
1047
1048
RSDK.StopSfx(HotaruHiWatt->sfxHHWAppear);
1049
RSDK.PlaySfx(HotaruHiWatt->sfxFlash, false, 255);
1050
1051
EntityFXFade *fxFade = CREATE_ENTITY(FXFade, INT_TO_VOID(0xF0F0F0), self->position.x, self->position.y);
1052
fxFade->speedIn = 128;
1053
fxFade->speedOut = 16;
1054
}
1055
}
1056
}
1057
1058
void HotaruHiWatt_StateBoss_FlashAppear(void)
1059
{
1060
RSDK_THIS(HotaruHiWatt);
1061
1062
RSDK.ProcessAnimation(&self->headAnimator);
1063
1064
self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);
1065
1066
self->velocity.x -= 0x3800;
1067
self->formationCircleRadius += self->velocity.x;
1068
1069
if (self->timer > 0)
1070
self->timer -= 8;
1071
1072
RSDK.SetLimitedFade(0, 1, 2, self->timer, 128, 192);
1073
1074
if (self->alpha > 0) {
1075
self->alpha -= 8;
1076
}
1077
1078
if (self->formationCircleRadius <= 0) {
1079
self->stateDraw = HotaruHiWatt_Draw_Boss;
1080
self->state = self->nextState;
1081
}
1082
}
1083
1084
void HotaruHiWatt_StateBoss_LaserAttackDelay(void)
1085
{
1086
RSDK_THIS(HotaruHiWatt);
1087
1088
RSDK.ProcessAnimation(&self->headAnimator);
1089
1090
self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);
1091
1092
if (++self->timer >= 24) {
1093
self->timer = 0;
1094
self->alpha = 0;
1095
self->stateDraw = HotaruHiWatt_Draw_BossLaserCharging;
1096
RSDK.SetSpriteAnimation(HotaruHiWatt->aniFrames, 2, &self->bulbFlashAnimator, true, 0);
1097
RSDK.SetSpriteAnimation(HotaruHiWatt->aniFrames, 7, &self->mainAnimator, true, 0);
1098
1099
RSDK.PlaySfx(HotaruHiWatt->sfxCharge, false, 255);
1100
self->state = HotaruHiWatt_StateBoss_ChargingLaser;
1101
}
1102
1103
HotaruHiWatt_CheckPlayerCollisions_Boss();
1104
}
1105
1106
void HotaruHiWatt_StateBoss_ChargingLaser(void)
1107
{
1108
RSDK_THIS(HotaruHiWatt);
1109
1110
RSDK.ProcessAnimation(&self->headAnimator);
1111
1112
self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);
1113
1114
HotaruHiWatt_CheckPlayerCollisions_Boss();
1115
1116
if (self->state == HotaruHiWatt_StateBoss_ChargingLaser) {
1117
if (self->alpha < 0x100)
1118
self->alpha += 4;
1119
1120
if (++self->timer >= 64) {
1121
self->timer = 0;
1122
self->velocity.x = 0;
1123
RSDK.SetSpriteAnimation(HotaruHiWatt->aniFrames, 3, &self->bulbFlashAnimator, true, 0);
1124
RSDK.SetSpriteAnimation(HotaruHiWatt->aniFrames, 3, &self->mainAnimator, true, 2);
1125
RSDK.SetSpriteAnimation(HotaruHiWatt->aniFrames, 4, &self->laserImpactAnimator, true, 0);
1126
1127
self->stateDraw = HotaruHiWatt_Draw_BossLaser;
1128
RSDK.StopSfx(HotaruHiWatt->sfxCharge);
1129
1130
if (self->position.x < HotaruHiWatt->boundsM)
1131
self->state = HotaruHiWatt_StateBoss_LaserAttack_Left;
1132
else
1133
self->state = HotaruHiWatt_StateBoss_LaserAttack_Right;
1134
}
1135
}
1136
}
1137
1138
// Right -> Left
1139
void HotaruHiWatt_StateBoss_LaserAttack_Right(void)
1140
{
1141
RSDK_THIS(HotaruHiWatt);
1142
1143
RSDK.ProcessAnimation(&self->headAnimator);
1144
RSDK.ProcessAnimation(&self->laserImpactAnimator);
1145
1146
self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);
1147
1148
self->velocity.x -= 0x1000;
1149
if (self->velocity.x < -0x20000)
1150
self->velocity.x = -0x20000;
1151
1152
self->position.x += self->velocity.x;
1153
1154
if (self->position.x <= HotaruHiWatt->boundsL) {
1155
self->position.x = HotaruHiWatt->boundsL;
1156
self->state = HotaruHiWatt_StateBoss_FinishedLaserAttack;
1157
}
1158
1159
int32 x = self->position.x;
1160
int32 y = self->position.y;
1161
self->position.y += 0x800000;
1162
RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0, 32);
1163
1164
self->laserImpactPos.x = self->position.x;
1165
self->laserImpactPos.y = self->position.y;
1166
1167
self->position.x = x;
1168
self->position.y = y;
1169
HotaruHiWatt_CheckPlayerCollisions_BossLaser();
1170
}
1171
1172
// Left -> Right
1173
void HotaruHiWatt_StateBoss_LaserAttack_Left(void)
1174
{
1175
RSDK_THIS(HotaruHiWatt);
1176
1177
RSDK.ProcessAnimation(&self->headAnimator);
1178
RSDK.ProcessAnimation(&self->laserImpactAnimator);
1179
1180
self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);
1181
1182
self->velocity.x += 4096;
1183
if (self->velocity.x > 0x20000)
1184
self->velocity.x = 0x20000;
1185
self->position.x += self->velocity.x;
1186
1187
if (self->position.x >= HotaruHiWatt->boundsR) {
1188
self->position.x = HotaruHiWatt->boundsR;
1189
self->state = HotaruHiWatt_StateBoss_FinishedLaserAttack;
1190
}
1191
1192
int32 x = self->position.x;
1193
int32 y = self->position.y;
1194
self->position.y += 0x800000;
1195
RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0, 32);
1196
1197
self->laserImpactPos.x = self->position.x;
1198
self->laserImpactPos.y = self->position.y;
1199
1200
self->position.x = x;
1201
self->position.y = y;
1202
HotaruHiWatt_CheckPlayerCollisions_BossLaser();
1203
}
1204
1205
void HotaruHiWatt_StateBoss_FinishedLaserAttack(void)
1206
{
1207
RSDK_THIS(HotaruHiWatt);
1208
1209
RSDK.ProcessAnimation(&self->headAnimator);
1210
1211
self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);
1212
1213
if (self->alpha > 0)
1214
self->alpha -= 4;
1215
1216
if (++self->timer >= 64) {
1217
self->laserImpactPos.y += 0x800000;
1218
self->timer = 0;
1219
self->stateDraw = HotaruHiWatt_Draw_Boss;
1220
self->velocity.y = 0;
1221
1222
RSDK.PlaySfx(HotaruHiWatt->sfxFlyUp, false, 255);
1223
self->state = HotaruHiWatt_StateBoss_FlyUp;
1224
}
1225
1226
HotaruHiWatt_CheckPlayerCollisions_Boss();
1227
}
1228
1229
void HotaruHiWatt_StateBoss_Destroyed(void)
1230
{
1231
RSDK_THIS(HotaruHiWatt);
1232
1233
HotaruHiWatt_Explode();
1234
1235
if (++self->timer == 60) {
1236
Debris_CreateFromEntries(HotaruHiWatt->aniFrames, HotaruHiWatt->debrisInfo, 8);
1237
self->visible = false;
1238
}
1239
else if (self->timer == 90) {
1240
Music_TransitionTrack(TRACK_STAGE, 0.0125);
1241
1242
self->timer = 0;
1243
self->state = HotaruHiWatt_StateBoss_Finished;
1244
self->visible = false;
1245
}
1246
}
1247
1248
void HotaruHiWatt_StateBoss_Finished(void)
1249
{
1250
RSDK_THIS(HotaruHiWatt);
1251
1252
if (++self->timer == 60) {
1253
foreach_all(SignPost, signPost)
1254
{
1255
signPost->position.x = self->position.x;
1256
signPost->active = ACTIVE_NORMAL;
1257
signPost->state = SignPost_State_Falling;
1258
RSDK.PlaySfx(SignPost->sfxTwinkle, false, 255);
1259
}
1260
1261
destroyEntity(self);
1262
}
1263
}
1264
1265
#if GAME_INCLUDE_EDITOR
1266
void HotaruHiWatt_EditorDraw(void)
1267
{
1268
RSDK_THIS(HotaruHiWatt);
1269
1270
self->drawFX = FX_FLIP;
1271
RSDK.SetSpriteAnimation(HotaruHiWatt->aniFrames, 0, &self->headAnimator, false, 0);
1272
RSDK.SetSpriteAnimation(HotaruHiWatt->aniFrames, 1, &self->bulbAnimator, false, 0);
1273
1274
self->direction = FLIP_NONE;
1275
RSDK.DrawSprite(&self->headAnimator, NULL, false);
1276
RSDK.DrawSprite(&self->bulbAnimator, NULL, false);
1277
1278
if (showGizmos()) {
1279
RSDK_DRAWING_OVERLAY(true);
1280
1281
DrawHelpers_DrawArenaBounds(-WIDE_SCR_XCENTER, -SCREEN_YSIZE, WIDE_SCR_XCENTER, 0, 1 | 2 | 4 | 8, 0x00C0F0);
1282
1283
RSDK_DRAWING_OVERLAY(false);
1284
}
1285
}
1286
1287
void HotaruHiWatt_EditorLoad(void)
1288
{
1289
HotaruHiWatt->aniFrames = RSDK.LoadSpriteAnimation("SSZ1/HotaruHiWatt.bin", SCOPE_STAGE);
1290
HotaruHiWatt->hotaruFrames = RSDK.LoadSpriteAnimation("SSZ1/HotaruMKII.bin", SCOPE_STAGE);
1291
}
1292
#endif
1293
1294
void HotaruHiWatt_Serialize(void) {}
1295
1296