Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/LRZ/HeavyRider.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: HeavyRider Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectHeavyRider *HeavyRider;
11
12
void HeavyRider_Update(void)
13
{
14
RSDK_THIS(HeavyRider);
15
16
StateMachine_Run(self->state);
17
}
18
19
void HeavyRider_LateUpdate(void) {}
20
21
void HeavyRider_StaticUpdate(void) {}
22
23
void HeavyRider_Draw(void)
24
{
25
RSDK_THIS(HeavyRider);
26
27
StateMachine_Run(self->stateDraw);
28
}
29
30
void HeavyRider_Create(void *data)
31
{
32
RSDK_THIS(HeavyRider);
33
34
self->drawFX = FX_ROTATE | FX_FLIP;
35
36
if (!SceneInfo->inEditor) {
37
if (globals->gameMode < MODE_TIMEATTACK) {
38
if (!self->type)
39
self->type = VOID_TO_INT(data);
40
41
switch (self->type) {
42
case HEAVYRIDER_RIDER:
43
self->active = ACTIVE_BOUNDS;
44
self->visible = false;
45
self->drawGroup = Zone->objectDrawGroup[1];
46
47
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 0, &self->mainAnimator, true, 0);
48
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 5, &self->thrustAnimator, true, 0);
49
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 7, &self->spikeBallAnimator, true, 0);
50
RSDK.SetSpriteAnimation(-1, 0, &self->fireballAnimator, true, 0);
51
52
self->updateRange.x = 0x800000;
53
self->updateRange.y = 0x800000;
54
55
HeavyRider->spikeBallAngle = 0x80;
56
HeavyRider->spikeBallState = HEAVYRIDER_SPIKEBALL_SWINGING;
57
HeavyRider->spawnDelay = 16;
58
HeavyRider->spawnFireballs = false;
59
HeavyRider->startY = self->position.y;
60
HeavyRider->curAttack = HEAVYRIDER_ATK_RIDING_SCREENBOUNDS;
61
HeavyRider->wheelExtendState = HEAVYRIDER_WHEEL_NONE;
62
HeavyRider->wheelLength = 0;
63
64
self->state = HeavyRider_State_SetupArena;
65
self->stateDraw = HeavyRider_Draw_Boss;
66
break;
67
68
case HEAVYRIDER_PLANESWITCH:
69
RSDK.SetSpriteAnimation(PlaneSwitch->aniFrames, 0, &self->mainAnimator, true, 0);
70
71
self->active = ACTIVE_BOUNDS;
72
self->updateRange.x = 0x200000;
73
self->updateRange.y = (self->size + 0x400) << 11;
74
self->visible = false;
75
self->drawGroup = Zone->objectDrawGroup[0];
76
77
self->state = HeavyRider_State_PlaneSwitch;
78
self->stateDraw = HeavyRider_Draw_PlaneSwitch;
79
break;
80
81
case HEAVYRIDER_FORCECHARGE_LEFT:
82
case HEAVYRIDER_FORCECHARGE_RIGHT:
83
case HEAVYRIDER_UNUSED1:
84
case HEAVYRIDER_UNUSED2:
85
RSDK.SetSpriteAnimation(PlaneSwitch->aniFrames, 0, &self->mainAnimator, true, ((self->type - 2) >> 1) + 4);
86
87
self->active = ACTIVE_BOUNDS;
88
self->updateRange.x = 0x200000;
89
self->updateRange.y = 0x200000;
90
self->visible = false;
91
self->drawGroup = Zone->objectDrawGroup[0];
92
93
self->state = HeavyRider_State_ChargeTrigger;
94
self->stateDraw = HeavyRider_Draw_Simple;
95
break;
96
97
case HEAVYRIDER_PUFF:
98
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 10, &self->mainAnimator, true, 0);
99
100
self->active = ACTIVE_NORMAL;
101
self->updateRange.x = 0x100000;
102
self->updateRange.y = 0x100000;
103
self->visible = true;
104
self->drawGroup = Zone->objectDrawGroup[1] - 1;
105
106
self->state = HeavyRider_State_Puff;
107
self->stateDraw = HeavyRider_Draw_Simple;
108
break;
109
110
case HEAVYRIDER_FIREBALL:
111
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 9, &self->mainAnimator, true, 0);
112
113
self->active = ACTIVE_NORMAL;
114
self->updateRange.x = 0x200000;
115
self->updateRange.y = 0x200000;
116
self->visible = true;
117
self->drawGroup = Zone->objectDrawGroup[1];
118
119
self->state = HeavyRider_State_Fireball;
120
self->stateDraw = HeavyRider_Draw_Simple;
121
break;
122
123
case HEAVYRIDER_JIMMY:
124
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 4, &self->mainAnimator, true, 0);
125
126
self->drawGroup = Zone->objectDrawGroup[1];
127
self->active = ACTIVE_NORMAL;
128
self->updateRange.x = 0x1800000;
129
self->updateRange.y = 0x1800000;
130
self->visible = true;
131
self->drawGroup = Zone->objectDrawGroup[1];
132
133
self->state = HeavyRider_StateJimmy_Idle;
134
self->stateDraw = HeavyRider_Draw_Simple;
135
break;
136
137
default: break;
138
}
139
}
140
else {
141
destroyEntity(self);
142
}
143
}
144
}
145
146
void HeavyRider_StageLoad(void)
147
{
148
HeavyRider->aniFrames = RSDK.LoadSpriteAnimation("LRZ3/HeavyRider.bin", SCOPE_STAGE);
149
150
HeavyRider->hitboxRider.left = -16;
151
HeavyRider->hitboxRider.top = -25;
152
HeavyRider->hitboxRider.right = 16;
153
HeavyRider->hitboxRider.bottom = 14;
154
155
HeavyRider->hitboxSpikeBall.left = -20;
156
HeavyRider->hitboxSpikeBall.top = -20;
157
HeavyRider->hitboxSpikeBall.right = 20;
158
HeavyRider->hitboxSpikeBall.bottom = 20;
159
160
HeavyRider->outerBox.left = -5;
161
HeavyRider->outerBox.top = 0;
162
HeavyRider->outerBox.right = 5;
163
HeavyRider->outerBox.bottom = 48;
164
165
HeavyRider->innerBox.left = -4;
166
HeavyRider->innerBox.top = 0;
167
HeavyRider->innerBox.right = 4;
168
HeavyRider->innerBox.bottom = 48;
169
170
HeavyRider->hitboxRiderTrigger.left = -4;
171
HeavyRider->hitboxRiderTrigger.top = 46;
172
HeavyRider->hitboxRiderTrigger.right = 4;
173
HeavyRider->hitboxRiderTrigger.bottom = 48;
174
175
HeavyRider->hitboxTrigger.left = -8;
176
HeavyRider->hitboxTrigger.top = -8;
177
HeavyRider->hitboxTrigger.right = 8;
178
HeavyRider->hitboxTrigger.bottom = 8;
179
180
HeavyRider->hitboxJimmy.left = -10;
181
HeavyRider->hitboxJimmy.top = 14;
182
HeavyRider->hitboxJimmy.right = 22;
183
HeavyRider->hitboxJimmy.bottom = 46;
184
185
HeavyRider->hitboxFireball.left = -2;
186
HeavyRider->hitboxFireball.top = 38;
187
HeavyRider->hitboxFireball.right = 14;
188
HeavyRider->hitboxFireball.bottom = 46;
189
190
HeavyRider->health = 8;
191
HeavyRider->invincibilityTimer = 0;
192
193
HeavyRider->sfxHit = RSDK.GetSfx("Stage/BossHit.wav");
194
HeavyRider->sfxExplosion = RSDK.GetSfx("Stage/Explosion2.wav");
195
HeavyRider->sfxCharge = RSDK.GetSfx("LRZ/RiderCharge.wav");
196
HeavyRider->sfxLaunch = RSDK.GetSfx("LRZ/RiderLaunch.wav");
197
HeavyRider->sfxSkid = RSDK.GetSfx("LRZ/RiderSkid.wav");
198
HeavyRider->sfxJump = RSDK.GetSfx("LRZ/RiderJump.wav");
199
HeavyRider->sfxCheer = RSDK.GetSfx("LRZ/RiderCheer.wav");
200
HeavyRider->sfxBumper = RSDK.GetSfx("Stage/Bumper3.wav");
201
}
202
203
void HeavyRider_SpawnDebris(int32 frame, uint8 drawGroup, int32 x, int32 y)
204
{
205
EntityDebris *debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, x, y);
206
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 7, &debris->animator, true, frame);
207
208
debris->velocity.x = RSDK.Rand(-0x20000, 0x20000);
209
debris->velocity.y = RSDK.Rand(-0x20000, -0x10000);
210
debris->drawGroup = drawGroup;
211
debris->gravityStrength = 0x4800;
212
debris->updateRange.x = 0x400000;
213
debris->updateRange.y = 0x400000;
214
}
215
216
void HeavyRider_CheckObjectCollisions(void)
217
{
218
RSDK_THIS(HeavyRider);
219
220
if (HeavyRider->invincibilityTimer) {
221
HeavyRider->invincibilityTimer--;
222
}
223
else {
224
foreach_active(Player, player)
225
{
226
int32 playerID = RSDK.GetEntitySlot(player);
227
228
if (HeavyRider->playerTimers[playerID])
229
HeavyRider->playerTimers[playerID]--;
230
231
if (Player_CheckBadnikTouch(player, self, &HeavyRider->hitboxRider)) {
232
if (Player_CheckBossHit(player, self)) {
233
HeavyRider_Hit();
234
foreach_break;
235
}
236
}
237
else if (Player_CheckBadnikTouch(player, self, &HeavyRider->hitboxJimmy)) {
238
if (!HeavyRider->playerTimers[playerID] && Player_CheckBossHit(player, self)) {
239
RSDK.PlaySfx(HeavyRider->sfxBumper, false, 255);
240
241
int32 angle = RSDK.ATan2(player->position.x - self->position.x - 0x60000, player->position.y - self->position.y - 0x1E0000);
242
player->velocity.x = 0x380 * RSDK.Cos256(angle);
243
244
if (player->position.x >= self->position.x) {
245
if (player->position.x > self->position.x) {
246
if (self->velocity.x > 0)
247
player->velocity.x += self->velocity.x;
248
}
249
}
250
else {
251
if (self->velocity.x >= 0) {
252
if (player->position.x > self->position.x) {
253
if (self->velocity.x > 0)
254
player->velocity.x += self->velocity.x;
255
}
256
}
257
else {
258
player->velocity.x += self->velocity.x;
259
}
260
}
261
262
player->velocity.y = 0x380 * RSDK.Sin256(angle);
263
if (player->velocity.y >= 0)
264
player->groundVel = player->velocity.x;
265
else
266
player->onGround = false;
267
268
player->applyJumpCap = false;
269
HeavyRider->playerTimers[playerID] = 15;
270
}
271
}
272
else if ((uint32)(HeavyRider->spikeBallAngle & 0x7F) + 32 < 0x40) {
273
int32 storeX = self->position.x;
274
int32 storeY = self->position.y;
275
self->position.x = HeavyRider->spikeBallPos.x;
276
self->position.y = HeavyRider->spikeBallPos.y;
277
278
if (Player_CheckCollisionTouch(player, self, &HeavyRider->hitboxSpikeBall)) {
279
#if MANIA_USE_PLUS
280
if (!Player_CheckMightyUnspin(player, 0x800, false, &player->uncurlTimer))
281
#endif
282
Player_Hurt(player, self);
283
}
284
285
self->position.x = storeX;
286
self->position.y = storeY;
287
}
288
}
289
}
290
291
if (HeavyRider->curAttack == HEAVYRIDER_ATK_RIDING_ARENABOUNDS || HeavyRider->curAttack == HEAVYRIDER_ATK_RIDING_USETRIGGERS) {
292
foreach_all(HeavyRider, rider)
293
{
294
if (rider->type == HEAVYRIDER_PLANESWITCH) {
295
if (abs(self->position.x - rider->position.x) < 0x100000 && abs(self->position.y - rider->position.y) < rider->size << 19) {
296
if (self->velocity.x >= 0)
297
self->collisionPlane = (rider->flags >> 3) & 1;
298
else
299
self->collisionPlane = (rider->flags >> 1) & 1;
300
}
301
}
302
else {
303
if (HeavyRider->curAttack == HEAVYRIDER_ATK_RIDING_USETRIGGERS && self->onGround) {
304
switch (rider->type) {
305
default: break;
306
307
case HEAVYRIDER_FORCECHARGE_LEFT:
308
if (RSDK.CheckObjectCollisionTouchBox(rider, &HeavyRider->hitboxTrigger, self, &HeavyRider->hitboxRiderTrigger)) {
309
if (self->direction == FLIP_X) {
310
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 2, &self->mainAnimator, true, 0);
311
RSDK.SetSpriteAnimation(-1, 0, &self->thrustAnimator, true, 0);
312
self->state = HeavyRider_State_Turning;
313
}
314
else if (self->state != HeavyRider_State_RampJump) {
315
self->timer = 38;
316
HeavyRider->chargeTimer = 0;
317
self->state = HeavyRider_State_RampJump;
318
}
319
}
320
break;
321
322
case HEAVYRIDER_FORCECHARGE_RIGHT:
323
if (RSDK.CheckObjectCollisionTouchBox(rider, &HeavyRider->hitboxTrigger, self, &HeavyRider->hitboxRiderTrigger)) {
324
if (self->direction == FLIP_NONE) {
325
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 2, &self->mainAnimator, true, 0);
326
RSDK.SetSpriteAnimation(-1, 0, &self->thrustAnimator, true, 0);
327
self->state = HeavyRider_State_Turning;
328
}
329
else if (self->state != HeavyRider_State_RampJump) {
330
self->timer = 38;
331
HeavyRider->chargeTimer = 0;
332
self->state = HeavyRider_State_RampJump;
333
}
334
}
335
break;
336
}
337
}
338
}
339
}
340
341
foreach_all(PlaneSwitch, planeSwitch) { PlaneSwitch_CheckCollisions(planeSwitch, self, planeSwitch->flags, planeSwitch->size, false, 0, 0); }
342
}
343
}
344
345
void HeavyRider_Hit(void)
346
{
347
RSDK_THIS(HeavyRider);
348
349
if (HeavyRider->health)
350
HeavyRider->health--;
351
352
if (!HeavyRider->health) {
353
RSDK.PlaySfx(HeavyRider->sfxExplosion, false, 255);
354
self->timer = 120;
355
356
if (HeavyRider->spikeBallState == HEAVYRIDER_SPIKEBALL_SWINGING) {
357
int32 spawnX = 0;
358
if (self->direction) {
359
if (self->mainAnimator.animationID == 2 && self->mainAnimator.frameID)
360
spawnX = self->position.x + 0x160000;
361
else
362
spawnX = self->position.x - 0xE0000;
363
}
364
else {
365
if (self->mainAnimator.animationID == 2 && self->mainAnimator.frameID)
366
spawnX = self->position.x - 0x160000;
367
else
368
spawnX = self->position.x + 0xE0000;
369
}
370
371
int32 angle = 0x400;
372
int32 cos = RSDK.Cos256(HeavyRider->spikeBallAngle);
373
for (int32 i = 0; i < 8; ++i) {
374
HeavyRider_SpawnDebris(1, Zone->objectDrawGroup[1], spawnX + angle * cos, self->position.y - 0x210000);
375
angle += 0x800;
376
}
377
378
HeavyRider_SpawnDebris(2, Zone->objectDrawGroup[1], spawnX + angle * cos, self->position.y - 0x210000);
379
HeavyRider->spikeBallState = HEAVYRIDER_SPIKEBALL_NONE;
380
381
RSDK_GET_ENTITY(SceneInfo->entitySlot + 1, Flamethrower)->interval = -1;
382
RSDK_GET_ENTITY(SceneInfo->entitySlot + 2, Flamethrower)->interval = -1;
383
384
HeavyRider->spawnFireballs = false;
385
RSDK.SetSpriteAnimation(-1, 0, &self->fireballAnimator, true, 0);
386
}
387
else if (HeavyRider->spikeBallState == HEAVYRIDER_SPIKEBALL_THROWN) {
388
HeavyRider_SpawnDebris(2, Zone->objectDrawGroup[1], HeavyRider->spikeBallPos.x, HeavyRider->spikeBallPos.y);
389
HeavyRider->spikeBallState = HEAVYRIDER_SPIKEBALL_NONE;
390
}
391
392
SceneInfo->timeEnabled = false;
393
Player_GiveScore(RSDK_GET_ENTITY(SLOT_PLAYER1, Player), 1000);
394
self->state = HeavyRider_State_Destroyed;
395
}
396
397
RSDK.PlaySfx(HeavyRider->sfxHit, false, 255);
398
self->timer -= 60;
399
HeavyRider->invincibilityTimer = 30;
400
}
401
402
void HeavyRider_Explode(void)
403
{
404
RSDK_THIS(HeavyRider);
405
406
if (!(Zone->timer & 7)) {
407
RSDK.PlaySfx(HeavyRider->sfxExplosion, false, 255);
408
409
if (!(Zone->timer & 0xF)) {
410
int32 x = self->position.x + (RSDK.Rand(-19, 20) << 16);
411
int32 y = self->position.y + (RSDK.Rand(-24, 25) << 16);
412
CREATE_ENTITY(Explosion, INT_TO_VOID((RSDK.Rand(0, 256) > 192) + EXPLOSION_BOSS), x, y)->drawGroup = Zone->objectDrawGroup[1] + 2;
413
}
414
}
415
}
416
417
void HeavyRider_HandleTurn_ScreenEdges(void)
418
{
419
RSDK_THIS(HeavyRider);
420
421
if (self->direction == FLIP_X) {
422
if (self->position.x < (ScreenInfo->position.x + 48) << 16) {
423
HeavyRider_DecideNextAttack();
424
425
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 2, &self->mainAnimator, true, 0);
426
RSDK.SetSpriteAnimation(-1, 0, &self->thrustAnimator, true, 0);
427
428
self->state = HeavyRider_State_Turning;
429
}
430
}
431
else {
432
if (self->position.x > (ScreenInfo->position.x + ScreenInfo->size.x - 48) << 16) {
433
HeavyRider_DecideNextAttack();
434
435
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 2, &self->mainAnimator, true, 0);
436
RSDK.SetSpriteAnimation(-1, 0, &self->thrustAnimator, true, 0);
437
438
self->state = HeavyRider_State_Turning;
439
}
440
}
441
}
442
443
void HeavyRider_HandleTurn_ArenaEdges(void)
444
{
445
RSDK_THIS(HeavyRider);
446
447
if (self->direction == FLIP_X) {
448
if (self->position.x < (Zone->cameraBoundsL[0] - 48) << 16) {
449
HeavyRider_DecideNextAttack();
450
451
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 2, &self->mainAnimator, true, 0);
452
RSDK.SetSpriteAnimation(-1, 0, &self->thrustAnimator, true, 0);
453
454
self->state = HeavyRider_State_Turning;
455
}
456
}
457
else {
458
if (self->position.x > (Zone->cameraBoundsR[0] + 48) << 16) {
459
HeavyRider_DecideNextAttack();
460
461
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 2, &self->mainAnimator, true, 0);
462
RSDK.SetSpriteAnimation(-1, 0, &self->thrustAnimator, true, 0);
463
464
self->state = HeavyRider_State_Turning;
465
}
466
}
467
}
468
469
void HeavyRider_DecideNextAttack(void)
470
{
471
RSDK_THIS(HeavyRider);
472
473
if (HeavyRider->curAttack != HEAVYRIDER_ATK_RIDING_USETRIGGERS) {
474
HeavyRider->spawnFireballs = 0;
475
RSDK.SetSpriteAnimation(-1, 0, &self->fireballAnimator, true, 0);
476
}
477
478
int32 atkID = RSDK.Rand(0, 10);
479
switch (HeavyRider->curAttack) {
480
case HEAVYRIDER_ATK_RIDING_SCREENBOUNDS: {
481
int32 nextAttacks[] = {
482
HEAVYRIDER_ATK_RIDING_SCREENBOUNDS, HEAVYRIDER_ATK_RIDING_SCREENBOUNDS, HEAVYRIDER_ATK_RIDING_ARENABOUNDS,
483
HEAVYRIDER_ATK_RIDING_ARENABOUNDS, HEAVYRIDER_ATK_RIDING_ARENABOUNDS, HEAVYRIDER_ATK_RIDING_ARENABOUNDS,
484
HEAVYRIDER_ATK_RIDING_USETRIGGERS, HEAVYRIDER_ATK_RIDING_USETRIGGERS, HEAVYRIDER_ATK_RIDING_USETRIGGERS,
485
HEAVYRIDER_ATK_RIDING_USETRIGGERS,
486
};
487
488
HeavyRider->curAttack = nextAttacks[atkID];
489
break;
490
}
491
492
case HEAVYRIDER_ATK_RIDING_ARENABOUNDS: {
493
int32 nextAttacks[] = {
494
HEAVYRIDER_ATK_RIDING_SCREENBOUNDS, HEAVYRIDER_ATK_RIDING_SCREENBOUNDS, HEAVYRIDER_ATK_RIDING_ARENABOUNDS,
495
HEAVYRIDER_ATK_RIDING_USETRIGGERS, HEAVYRIDER_ATK_RIDING_USETRIGGERS, HEAVYRIDER_ATK_RIDING_USETRIGGERS,
496
HEAVYRIDER_ATK_PREPCHARGE, HEAVYRIDER_ATK_PREPCHARGE, HEAVYRIDER_ATK_PREPCHARGE,
497
HEAVYRIDER_ATK_PREPCHARGE,
498
};
499
500
HeavyRider->curAttack = nextAttacks[atkID];
501
break;
502
}
503
504
case HEAVYRIDER_ATK_RIDING_USETRIGGERS: {
505
int32 nextAttacks[] = {
506
HEAVYRIDER_ATK_RIDING_SCREENBOUNDS, HEAVYRIDER_ATK_RIDING_SCREENBOUNDS, HEAVYRIDER_ATK_RIDING_ARENABOUNDS,
507
HEAVYRIDER_ATK_RIDING_ARENABOUNDS, HEAVYRIDER_ATK_RIDING_ARENABOUNDS, HEAVYRIDER_ATK_RIDING_USETRIGGERS,
508
HEAVYRIDER_ATK_PREPCHARGE, HEAVYRIDER_ATK_PREPCHARGE, HEAVYRIDER_ATK_PREPCHARGE,
509
HEAVYRIDER_ATK_PREPCHARGE,
510
};
511
512
HeavyRider->curAttack = nextAttacks[atkID];
513
514
if (HeavyRider->curAttack != HEAVYRIDER_ATK_PREPCHARGE) {
515
HeavyRider->spawnFireballs = false;
516
RSDK.SetSpriteAnimation(-1, 0, &self->fireballAnimator, true, 0);
517
}
518
break;
519
}
520
521
case HEAVYRIDER_ATK_PREPCHARGE:
522
case HEAVYRIDER_ATK_CHARGE: {
523
int32 nextAttack[] = {
524
HEAVYRIDER_ATK_RIDING_SCREENBOUNDS, HEAVYRIDER_ATK_RIDING_SCREENBOUNDS, HEAVYRIDER_ATK_RIDING_SCREENBOUNDS,
525
HEAVYRIDER_ATK_PREPCHARGE, HEAVYRIDER_ATK_PREPCHARGE, HEAVYRIDER_ATK_RIDING_ARENABOUNDS,
526
HEAVYRIDER_ATK_RIDING_ARENABOUNDS, HEAVYRIDER_ATK_RIDING_ARENABOUNDS, HEAVYRIDER_ATK_RIDING_USETRIGGERS,
527
HEAVYRIDER_ATK_RIDING_USETRIGGERS,
528
};
529
530
HeavyRider->curAttack = nextAttack[atkID];
531
break;
532
}
533
534
default: break;
535
}
536
}
537
538
void HeavyRider_State_SetupArena(void)
539
{
540
RSDK_THIS(HeavyRider);
541
542
if (++self->timer >= 2) {
543
self->timer = 0;
544
Zone->playerBoundActiveR[0] = true;
545
Zone->cameraBoundsR[0] = (self->position.x >> 16) + WIDE_SCR_XSIZE;
546
self->active = ACTIVE_NORMAL;
547
548
foreach_all(BoundsMarker, marker) { destroyEntity(marker); }
549
self->state = HeavyRider_State_AwaitPlayer;
550
}
551
}
552
553
void HeavyRider_State_AwaitPlayer(void)
554
{
555
RSDK_THIS(HeavyRider);
556
557
Zone->playerBoundActiveL[0] = true;
558
Zone->cameraBoundsL[0] = ScreenInfo->position.x;
559
560
EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
561
if (player1->position.x > self->position.x - 0x500000) {
562
Zone->playerBoundActiveL[0] = true;
563
Zone->cameraBoundsL[0] = (self->position.x >> 16) - WIDE_SCR_XSIZE;
564
#if MANIA_USE_PLUS
565
HeavyRider->outro = CREATE_ENTITY(LRZ3Outro, NULL, self->position.x, self->position.y);
566
#endif
567
self->state = HeavyRider_State_SetupRider;
568
}
569
}
570
571
void HeavyRider_State_SetupRider(void)
572
{
573
RSDK_THIS(HeavyRider);
574
575
Zone->playerBoundActiveL[0] = true;
576
577
#if MANIA_USE_PLUS
578
EntityLRZ3Outro *outro = HeavyRider->outro;
579
if (outro->state == LRZ3Outro_State_EnterLittlePlanet) {
580
#else
581
EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
582
if (player1->position.x > self->position.x) {
583
#endif
584
585
self->position.y -= 0x400000;
586
self->position.x = (Zone->cameraBoundsL[0] - 64) << 16;
587
self->onGround = false;
588
self->tileCollisions = TILECOLLISION_DOWN;
589
self->collisionPlane = 0;
590
self->collisionLayers = (1 << Zone->fgLayer[0]) | (1 << Zone->fgLayer[1]);
591
592
Music_TransitionTrack(TRACK_HBHBOSS, 0.0125);
593
594
self->visible = true;
595
self->state = HeavyRider_State_Moving;
596
self->velocity.x = 0;
597
self->timer = 0;
598
}
599
}
600
601
void HeavyRider_State_Moving(void)
602
{
603
RSDK_THIS(HeavyRider);
604
605
RSDK.ProcessAnimation(&self->mainAnimator);
606
RSDK.ProcessAnimation(&self->thrustAnimator);
607
RSDK.ProcessAnimation(&self->fireballAnimator);
608
609
RSDK.ProcessObjectMovement(self, &HeavyRider->outerBox, &HeavyRider->innerBox);
610
611
if (self->onGround) {
612
if (self->velocity.y <= 0x20000) {
613
self->velocity.y = 0;
614
}
615
else {
616
self->velocity.y = (self->velocity.y >> 1) - self->velocity.y;
617
if (self->velocity.y > 0) {
618
if (RSDK.Rand(0, 2) == 1) {
619
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 2, &self->mainAnimator, true, 0);
620
RSDK.SetSpriteAnimation(-1, 0, &self->thrustAnimator, true, 0);
621
self->state = HeavyRider_State_Turning;
622
}
623
self->velocity.y = 0;
624
}
625
else {
626
self->onGround = false;
627
RSDK_GET_ENTITY(SceneInfo->entitySlot + 1, Flamethrower)->interval = -1;
628
RSDK_GET_ENTITY(SceneInfo->entitySlot + 2, Flamethrower)->interval = -1;
629
}
630
}
631
}
632
else {
633
self->velocity.y += 0x3800;
634
}
635
636
if (HeavyRider->wheelExtendState == HEAVYRIDER_WHEEL_EXTENDING) {
637
if (HeavyRider->wheelLength < 0x100000)
638
HeavyRider->wheelLength += 0x30000;
639
640
if (HeavyRider->wheelLength > 0x100000) {
641
HeavyRider->wheelLength = 0x100000;
642
HeavyRider->wheelExtendState = HEAVYRIDER_WHEEL_RETRACTING;
643
}
644
}
645
else if (HeavyRider->wheelExtendState == HEAVYRIDER_WHEEL_RETRACTING) {
646
if (HeavyRider->wheelLength > 0)
647
HeavyRider->wheelLength -= 0x30000;
648
649
if (HeavyRider->wheelLength < 0) {
650
HeavyRider->wheelLength = 0;
651
HeavyRider->wheelExtendState = HEAVYRIDER_WHEEL_NONE;
652
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 0, &self->mainAnimator, true, 0);
653
RSDK.SetSpriteAnimation(-1, 0, &self->wheelieAnimator, true, 0);
654
}
655
}
656
657
EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
658
if (self->position.y == HeavyRider->startY && HeavyRider->curAttack != HEAVYRIDER_ATK_CHARGE && player1->onGround) {
659
int32 dist = 0x7FFFFFFF;
660
if (self->velocity.x <= 0) {
661
if (player1->position.x < self->position.x) {
662
dist = self->position.x - player1->position.x;
663
664
if (player1->velocity.x > 0)
665
dist -= 8 * player1->velocity.x;
666
}
667
}
668
else {
669
if (player1->position.x > self->position.x) {
670
dist = player1->position.x - self->position.x;
671
672
if (player1->velocity.x < 0)
673
dist += 8 * player1->velocity.x;
674
}
675
}
676
677
if (dist < 0x480000) {
678
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 11, &self->mainAnimator, true, 0);
679
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 11, &self->wheelieAnimator, true, 0);
680
681
RSDK.PlaySfx(HeavyRider->sfxJump, false, 255);
682
self->onGround = false;
683
self->velocity.y = -0x58000;
684
685
HeavyRider->wheelExtendState = HEAVYRIDER_WHEEL_EXTENDING;
686
HeavyRider->wheelLength = 0;
687
}
688
}
689
690
if (self->direction) {
691
if (self->groundVel > -0x40000)
692
self->groundVel -= 0x4000;
693
}
694
else {
695
if (self->groundVel < 0x40000)
696
self->groundVel += 0x4000;
697
}
698
699
switch (HeavyRider->curAttack) {
700
case HEAVYRIDER_ATK_RIDING_SCREENBOUNDS: HeavyRider_HandleTurn_ScreenEdges(); break;
701
702
case HEAVYRIDER_ATK_RIDING_ARENABOUNDS:
703
case HEAVYRIDER_ATK_RIDING_USETRIGGERS:
704
case HEAVYRIDER_ATK_CHARGE: HeavyRider_HandleTurn_ArenaEdges(); break;
705
706
case HEAVYRIDER_ATK_PREPCHARGE:
707
HeavyRider_HandleTurn_ArenaEdges();
708
709
HeavyRider->curAttack = HEAVYRIDER_ATK_CHARGE;
710
HeavyRider->spikeBallState = HEAVYRIDER_SPIKEBALL_THROWN;
711
712
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 1, &self->mainAnimator, true, 2);
713
714
self->timer = 41;
715
HeavyRider->chargeTimer = 0;
716
self->state = HeavyRider_State_Charging;
717
break;
718
719
default: break;
720
}
721
722
if (self->mainAnimator.animationID != 2) {
723
if (abs(self->groundVel) > 0x48000 || HeavyRider->spawnFireballs) {
724
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 5, &self->thrustAnimator, false, 0);
725
726
if (HeavyRider->spawnFireballs && self->onGround) {
727
if (!--HeavyRider->spawnDelay) {
728
HeavyRider->spawnDelay = 10;
729
CREATE_ENTITY(HeavyRider, INT_TO_VOID(HEAVYRIDER_FIREBALL), self->position.x, self->position.y);
730
}
731
}
732
}
733
else {
734
RSDK.SetSpriteAnimation(-1, 0, &self->thrustAnimator, true, 0);
735
736
if (HeavyRider->spawnDelay > 16)
737
HeavyRider->spawnDelay = 16;
738
739
if (!--HeavyRider->spawnDelay) {
740
HeavyRider->spawnDelay = 16;
741
EntityHeavyRider *child = CREATE_ENTITY(HeavyRider, INT_TO_VOID(HEAVYRIDER_PUFF), self->position.x, self->position.y + 0x1C0000);
742
if (self->direction == FLIP_X)
743
child->position.x += 0x110000;
744
else
745
child->position.x -= 0x110000;
746
}
747
}
748
}
749
750
if (HeavyRider->spikeBallState == HEAVYRIDER_SPIKEBALL_SWINGING)
751
HeavyRider->spikeBallAngle += 6;
752
753
if (HeavyRider->spikeBallState == HEAVYRIDER_SPIKEBALL_THROWN) {
754
HeavyRider->spikeBallAngle = 0;
755
HeavyRider->spikeBallPos.x = self->position.x;
756
HeavyRider->spikeBallPos.y = self->position.y;
757
758
if (self->direction)
759
HeavyRider->spikeBallPos.x -= 0x200000;
760
else
761
HeavyRider->spikeBallPos.x += 0x200000;
762
763
HeavyRider->spikeBallPos.y += 0xC0000;
764
}
765
766
HeavyRider_CheckObjectCollisions();
767
}
768
769
void HeavyRider_State_RampJump(void)
770
{
771
RSDK_THIS(HeavyRider);
772
773
float chargeSpeeds[] = { 1.0, 1.1926451, 1.4150375, 1.6780719, 2.0 };
774
775
HeavyRider_State_Moving();
776
777
if (self->type != HEAVYRIDER_JIMMY && self->timer == 30) {
778
RSDK_GET_ENTITY(SceneInfo->entitySlot + 1, Flamethrower)->interval = 0;
779
RSDK_GET_ENTITY(SceneInfo->entitySlot + 2, Flamethrower)->interval = 0;
780
}
781
782
if (--self->timer > 0) {
783
if (!(self->timer & 7)) {
784
int32 channel = RSDK.PlaySfx(HeavyRider->sfxCharge, false, 255);
785
RSDK.SetChannelAttributes(channel, 1.0, 0.0, chargeSpeeds[HeavyRider->chargeTimer]);
786
++HeavyRider->chargeTimer;
787
}
788
}
789
else {
790
RSDK.PlaySfx(HeavyRider->sfxLaunch, false, 255);
791
self->timer = 30;
792
self->groundVel += (self->groundVel >> 2) + (self->groundVel >> 1);
793
if (self->type == HEAVYRIDER_JIMMY)
794
self->state = HeavyRider_State_Moving;
795
else
796
self->state = HeavyRider_State_ChargeDash;
797
}
798
}
799
800
void HeavyRider_State_Charging(void)
801
{
802
RSDK_THIS(HeavyRider);
803
804
float chargeSpeeds[] = { 1.0, 1.1926451, 1.4150375, 1.6780719, 2.0 };
805
806
HeavyRider_State_Moving();
807
808
if (--self->timer > 0) {
809
if (!(self->timer & 7)) {
810
int32 channel = RSDK.PlaySfx(HeavyRider->sfxCharge, false, 255);
811
RSDK.SetChannelAttributes(channel, 1.0, 0.0, chargeSpeeds[HeavyRider->chargeTimer]);
812
++HeavyRider->chargeTimer;
813
}
814
}
815
else {
816
RSDK.PlaySfx(HeavyRider->sfxLaunch, false, 255);
817
self->timer = 30;
818
self->groundVel += (self->groundVel >> 2) + (self->groundVel >> 1);
819
self->state = HeavyRider_State_Moving;
820
}
821
}
822
823
void HeavyRider_State_ChargeDash(void)
824
{
825
RSDK_THIS(HeavyRider);
826
827
HeavyRider_State_Moving();
828
829
if (--self->timer == 16) {
830
HeavyRider->spawnDelay = 10;
831
HeavyRider->spawnFireballs = true;
832
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 8, &self->fireballAnimator, true, 0);
833
}
834
else if (self->timer <= 0) {
835
for (int32 i = 0; i < 0x60; ++i) {
836
int32 x = RSDK.Rand(-128, 129);
837
int32 y = 2 * RSDK.Rand(4, 16);
838
EntityDebris *debris = CREATE_ENTITY(Debris, NULL, (x << 16) + self->position.x, (ScreenInfo->position.y - y) << 16);
839
840
debris->updateRange.x = 0x2000000;
841
debris->updateRange.y = 0x2000000;
842
debris->state = Debris_State_Fall;
843
debris->gravityStrength = 0x1800;
844
debris->velocity.x = RSDK.Rand(-2, 3) << 16;
845
debris->velocity.y = RSDK.Rand(-2, 2) << 16;
846
debris->drawFX = FX_FLIP;
847
debris->direction = i & 3;
848
debris->drawGroup = Zone->objectDrawGroup[1];
849
850
int32 frame = RSDK.Rand(0, 4);
851
int32 anim = RSDK.Rand(12, 15);
852
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, anim, &debris->animator, true, frame);
853
}
854
855
RSDK.PlaySfx(HeavyRider->sfxCheer, false, 255);
856
self->state = HeavyRider_State_Moving;
857
}
858
}
859
860
void HeavyRider_State_Turning(void)
861
{
862
RSDK_THIS(HeavyRider);
863
864
RSDK.ProcessAnimation(&self->mainAnimator);
865
RSDK.ProcessAnimation(&self->fireballAnimator);
866
867
RSDK.ProcessObjectMovement(self, &HeavyRider->outerBox, &HeavyRider->innerBox);
868
869
if (self->onGround) {
870
if (self->velocity.y <= 0x20000) {
871
if (!(Zone->timer & 3))
872
RSDK.PlaySfx(HeavyRider->sfxSkid, false, 255);
873
874
self->velocity.y = 0;
875
}
876
else {
877
self->velocity.y = (self->velocity.y >> 1) - self->velocity.y;
878
879
if ((self->velocity.y >> 1) - self->velocity.y <= 0)
880
self->onGround = false;
881
else
882
self->velocity.y = 0;
883
}
884
}
885
else {
886
self->velocity.y += 0x3800;
887
}
888
889
if (self->direction) {
890
if (self->groundVel > -0x40000)
891
self->groundVel -= 0x4000;
892
}
893
else {
894
if (self->groundVel < 0x40000)
895
self->groundVel += 0x4000;
896
}
897
898
if (self->mainAnimator.frameID == self->mainAnimator.frameCount - 1) {
899
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 0, &self->mainAnimator, true, 0);
900
self->direction ^= FLIP_X;
901
HeavyRider->spikeBallState = HEAVYRIDER_SPIKEBALL_SWINGING;
902
self->state = HeavyRider_State_Moving;
903
}
904
905
HeavyRider->spikeBallAngle += 4;
906
907
HeavyRider_CheckObjectCollisions();
908
}
909
910
void HeavyRider_State_Destroyed(void)
911
{
912
RSDK_THIS(HeavyRider);
913
914
RSDK.ProcessAnimation(&self->mainAnimator);
915
RSDK.ProcessAnimation(&self->thrustAnimator);
916
917
HeavyRider_Explode();
918
919
if (--self->timer <= 0) {
920
EntityHeavyRider *child = CREATE_ENTITY(HeavyRider, INT_TO_VOID(HEAVYRIDER_JIMMY), self->position.x, self->position.y);
921
child->direction = self->direction;
922
child->onGround = false;
923
child->tileCollisions = TILECOLLISION_DOWN;
924
child->collisionLayers = (1 << Zone->fgLayer[0]) | (1 << Zone->fgLayer[1]);
925
child->collisionPlane = 0;
926
self->velocity.y = -0x60000;
927
928
if (self->direction == FLIP_NONE)
929
self->velocity.x = -0x20000;
930
else
931
self->velocity.x = 0x20000;
932
933
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 3, &self->mainAnimator, true, 0);
934
RSDK.SetSpriteAnimation(-1, 0, &self->thrustAnimator, true, 0);
935
936
self->state = HeavyRider_State_Finish;
937
}
938
}
939
940
void HeavyRider_State_Finish(void)
941
{
942
RSDK_THIS(HeavyRider);
943
944
if (++self->timer < 45)
945
HeavyRider_Explode();
946
947
RSDK.ProcessAnimation(&self->mainAnimator);
948
RSDK.ProcessAnimation(&self->thrustAnimator);
949
950
self->position.x += self->velocity.x;
951
self->position.y += self->velocity.y;
952
self->velocity.y += 0x3800;
953
954
if (self->velocity.y > 0)
955
self->drawGroup = Zone->objectDrawGroup[1];
956
957
if (!RSDK.CheckOnScreen(self, &self->updateRange)) {
958
Music_TransitionTrack(TRACK_STAGE, 0.0125);
959
960
self->position.x = (ScreenInfo->position.x + ScreenInfo->center.x) << 16;
961
self->position.y = (ScreenInfo->position.y - 48) << 16;
962
963
EntityEggPrison *prison = CREATE_ENTITY(EggPrison, INT_TO_VOID(EGGPRISON_FLYING), self->position.x, self->position.y);
964
prison->isPermanent = true;
965
prison->drawGroup = Zone->objectDrawGroup[1];
966
967
destroyEntity(self);
968
}
969
}
970
971
void HeavyRider_Draw_Boss(void)
972
{
973
RSDK_THIS(HeavyRider);
974
975
if (HeavyRider->wheelExtendState != HEAVYRIDER_WHEEL_NONE) {
976
Vector2 drawPos = self->position;
977
drawPos.y += 2 * HeavyRider->wheelLength;
978
self->wheelieAnimator.frameID = 3;
979
RSDK.DrawSprite(&self->wheelieAnimator, &drawPos, false);
980
981
self->wheelieAnimator.frameID = 2;
982
RSDK.DrawSprite(&self->wheelieAnimator, &drawPos, false);
983
984
drawPos.y -= HeavyRider->wheelLength;
985
self->wheelieAnimator.frameID = 1;
986
RSDK.DrawSprite(&self->wheelieAnimator, &drawPos, false);
987
}
988
989
int32 drawX = 0;
990
if (self->direction) {
991
if (self->mainAnimator.animationID == 2 && self->mainAnimator.frameID)
992
drawX = self->position.x + 0x160000;
993
else
994
drawX = self->position.x - 0xE0000;
995
}
996
else if (self->mainAnimator.animationID == 2 && self->mainAnimator.frameID)
997
drawX = self->position.x - 0x160000;
998
else
999
drawX = self->position.x + 0xE0000;
1000
1001
int32 drawY = self->position.y - 0x210000;
1002
Vector2 drawPos;
1003
drawPos.x = drawX;
1004
drawPos.y = drawY;
1005
1006
if (HeavyRider->spikeBallState != HEAVYRIDER_SPIKEBALL_NONE) {
1007
if (HeavyRider->spikeBallState <= HEAVYRIDER_SPIKEBALL_UNUSED3) {
1008
if (HeavyRider->spikeBallAngle >= 0x80) {
1009
self->spikeBallAnimator.frameID = 2;
1010
drawPos.x = drawX + 0x4400 * RSDK.Cos256(HeavyRider->spikeBallAngle);
1011
drawPos.y = drawY + 0x880 * RSDK.Sin256(2 * HeavyRider->spikeBallAngle);
1012
self->drawFX |= FX_SCALE;
1013
self->scale.x = (RSDK.Sin256(HeavyRider->spikeBallAngle) >> 2) + 0x200;
1014
self->scale.y = (RSDK.Sin256(HeavyRider->spikeBallAngle) >> 2) + 0x200;
1015
RSDK.DrawSprite(&self->spikeBallAnimator, &drawPos, false);
1016
1017
self->drawFX &= ~FX_SCALE;
1018
HeavyRider->spikeBallPos = drawPos;
1019
1020
self->spikeBallAnimator.frameID = 1;
1021
int32 angle = 0x4400;
1022
for (int32 i = 0; i < 8; ++i) {
1023
angle -= 0x800;
1024
drawPos.x = drawX + angle * RSDK.Cos256(HeavyRider->spikeBallAngle);
1025
drawPos.y = drawY + (angle >> 3) * RSDK.Sin256(2 * HeavyRider->spikeBallAngle);
1026
RSDK.DrawSprite(&self->spikeBallAnimator, &drawPos, false);
1027
}
1028
}
1029
}
1030
else {
1031
if (HeavyRider->spikeBallState == HEAVYRIDER_SPIKEBALL_THROWN) {
1032
self->spikeBallAnimator.frameID = 2;
1033
RSDK.DrawSprite(&self->spikeBallAnimator, &HeavyRider->spikeBallPos, false);
1034
}
1035
}
1036
}
1037
1038
if (HeavyRider->invincibilityTimer & 1)
1039
RSDK.SetPaletteEntry(0, 128, 0xE0E0E0);
1040
1041
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
1042
1043
RSDK.SetPaletteEntry(0, 128, 0x000000);
1044
1045
RSDK.DrawSprite(&self->thrustAnimator, NULL, false);
1046
1047
switch (HeavyRider->spikeBallState) {
1048
default:
1049
case HEAVYRIDER_SPIKEBALL_NONE:
1050
case HEAVYRIDER_SPIKEBALL_THROWN: RSDK.DrawSprite(&self->fireballAnimator, NULL, false); break;
1051
1052
case HEAVYRIDER_SPIKEBALL_SWINGING:
1053
case HEAVYRIDER_SPIKEBALL_UNUSED1:
1054
case HEAVYRIDER_SPIKEBALL_UNUSED2:
1055
case HEAVYRIDER_SPIKEBALL_UNUSED3:
1056
if (HeavyRider->spikeBallAngle < 0x80) {
1057
self->spikeBallAnimator.frameID = 1;
1058
int32 angle = 0x400;
1059
for (int32 i = 0; i < 8; ++i) {
1060
angle += 0x800;
1061
drawPos.x = drawX + angle * RSDK.Cos256(HeavyRider->spikeBallAngle);
1062
drawPos.y = drawY + (angle >> 3) * RSDK.Sin256(2 * HeavyRider->spikeBallAngle);
1063
RSDK.DrawSprite(&self->spikeBallAnimator, &drawPos, false);
1064
}
1065
1066
self->spikeBallAnimator.frameID = 2;
1067
drawPos.x = drawX + angle * RSDK.Cos256(HeavyRider->spikeBallAngle);
1068
drawPos.y = drawY + (angle >> 3) * RSDK.Sin256(2 * HeavyRider->spikeBallAngle);
1069
self->drawFX |= FX_SCALE;
1070
self->scale.x = (RSDK.Sin256(HeavyRider->spikeBallAngle) >> 2) + 0x200;
1071
self->scale.y = (RSDK.Sin256(HeavyRider->spikeBallAngle) >> 2) + 0x200;
1072
RSDK.DrawSprite(&self->spikeBallAnimator, &drawPos, false);
1073
1074
self->drawFX &= ~FX_SCALE;
1075
HeavyRider->spikeBallPos = drawPos;
1076
}
1077
1078
RSDK.DrawSprite(&self->fireballAnimator, NULL, false);
1079
break;
1080
1081
case HEAVYRIDER_SPIKEBALL_UNUSED4:
1082
case HEAVYRIDER_SPIKEBALL_UNUSED5:
1083
RSDK.DrawSprite(&self->spikeBallAnimator, &HeavyRider->spikeBallPos, false);
1084
RSDK.DrawSprite(&self->fireballAnimator, NULL, false);
1085
break;
1086
}
1087
}
1088
1089
void HeavyRider_State_PlaneSwitch(void)
1090
{
1091
RSDK_THIS(HeavyRider);
1092
1093
if (self->affectPlayer) {
1094
foreach_active(Player, player)
1095
{
1096
if (abs(player->position.x - self->position.x) < 0x100000 && abs(player->position.y - self->position.y) < self->size << 19) {
1097
if (player->velocity.x >= 0) {
1098
player->collisionPlane = (self->flags >> 3) & 1;
1099
1100
if (!(self->flags & 4)) {
1101
player->collisionLayers = 1 << Zone->fgLayer[0];
1102
Zone->collisionLayers = 1 << Zone->fgLayer[0];
1103
}
1104
else {
1105
player->collisionLayers = 1 << Zone->fgLayer[1];
1106
Zone->collisionLayers = 1 << Zone->fgLayer[1];
1107
}
1108
}
1109
else {
1110
player->collisionPlane = (self->flags >> 1) & 1;
1111
1112
if (!(self->flags & 1)) {
1113
player->collisionLayers = 1 << Zone->fgLayer[0];
1114
Zone->collisionLayers = 1 << Zone->fgLayer[0];
1115
}
1116
else {
1117
player->collisionLayers = 1 << Zone->fgLayer[1];
1118
Zone->collisionLayers = 1 << Zone->fgLayer[1];
1119
}
1120
}
1121
}
1122
}
1123
}
1124
1125
self->visible = DebugMode->debugActive;
1126
}
1127
1128
void HeavyRider_Draw_PlaneSwitch(void)
1129
{
1130
RSDK_THIS(HeavyRider);
1131
1132
Vector2 drawPos = self->position;
1133
drawPos.x -= 0x80000;
1134
drawPos.y -= self->size << 19;
1135
Zone_RotateOnPivot(&drawPos, &self->position, self->angle);
1136
1137
self->mainAnimator.frameID = self->flags & 3;
1138
for (int32 i = 0; i < self->size; ++i) {
1139
RSDK.DrawSprite(&self->mainAnimator, &drawPos, 0);
1140
drawPos.x += RSDK.Sin256(self->angle) << 12;
1141
drawPos.y += RSDK.Cos256(self->angle) << 12;
1142
}
1143
1144
drawPos.x = self->position.x + TO_FIXED(8);
1145
drawPos.y = self->position.y - (self->size << 19);
1146
Zone_RotateOnPivot(&drawPos, &self->position, self->angle);
1147
1148
self->mainAnimator.frameID = (self->flags >> 2) & 3;
1149
for (int32 i = 0; i < self->size; ++i) {
1150
RSDK.DrawSprite(&self->mainAnimator, &drawPos, 0);
1151
drawPos.x += RSDK.Sin256(self->angle) << 12;
1152
drawPos.y += RSDK.Cos256(self->angle) << 12;
1153
}
1154
}
1155
1156
void HeavyRider_State_ChargeTrigger(void)
1157
{
1158
RSDK_THIS(HeavyRider);
1159
1160
self->visible = DebugMode->debugActive;
1161
}
1162
1163
void HeavyRider_Draw_Simple(void)
1164
{
1165
RSDK_THIS(HeavyRider);
1166
1167
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
1168
}
1169
1170
void HeavyRider_State_Fireball(void)
1171
{
1172
RSDK_THIS(HeavyRider);
1173
1174
RSDK.ProcessAnimation(&self->mainAnimator);
1175
1176
if (self->mainAnimator.frameID == self->mainAnimator.frameCount - 1) {
1177
destroyEntity(self);
1178
}
1179
else {
1180
foreach_active(Player, player)
1181
{
1182
if (Player_CheckCollisionTouch(player, self, &HeavyRider->hitboxFireball)) {
1183
Player_ElementHurt(player, self, SHIELD_FIRE);
1184
}
1185
}
1186
}
1187
}
1188
1189
void HeavyRider_State_Puff(void)
1190
{
1191
RSDK_THIS(HeavyRider);
1192
1193
RSDK.ProcessAnimation(&self->mainAnimator);
1194
1195
if (self->mainAnimator.frameID == self->mainAnimator.frameCount - 1)
1196
destroyEntity(self);
1197
}
1198
1199
void HeavyRider_StateJimmy_Idle(void)
1200
{
1201
RSDK_THIS(HeavyRider);
1202
1203
RSDK.ProcessAnimation(&self->mainAnimator);
1204
1205
if (++self->timer >= 45) {
1206
self->timer = 38;
1207
HeavyRider->chargeTimer = 0;
1208
self->state = HeavyRider_StateJimmy_RevUp;
1209
}
1210
}
1211
1212
void HeavyRider_StateJimmy_RevRelease(void)
1213
{
1214
RSDK_THIS(HeavyRider);
1215
1216
RSDK.ProcessAnimation(&self->mainAnimator);
1217
RSDK.ProcessAnimation(&self->thrustAnimator);
1218
1219
RSDK.ProcessObjectMovement(self, &HeavyRider->outerBox, &HeavyRider->innerBox);
1220
1221
if (self->onGround) {
1222
if (self->velocity.y <= 0x20000)
1223
self->velocity.y = 0;
1224
else
1225
self->velocity.y = (self->velocity.y >> 1) - self->velocity.y;
1226
}
1227
else {
1228
self->velocity.y += 0x3800;
1229
}
1230
1231
if (self->direction)
1232
self->groundVel -= 0x8000;
1233
else
1234
self->groundVel += 0x8000;
1235
1236
if (!RSDK.CheckOnScreen(self, &self->updateRange))
1237
destroyEntity(self);
1238
}
1239
1240
void HeavyRider_StateJimmy_RevUp(void)
1241
{
1242
RSDK_THIS(HeavyRider);
1243
1244
float chargeSpeeds[] = { 1.0, 1.1926451, 1.4150375, 1.6780719, 2.0 };
1245
1246
RSDK.ProcessAnimation(&self->mainAnimator);
1247
1248
if (--self->timer > 0) {
1249
if (!(self->timer & 7)) {
1250
int32 channel = RSDK.PlaySfx(HeavyRider->sfxCharge, false, 255);
1251
RSDK.SetChannelAttributes(channel, 1.0, 0.0, chargeSpeeds[HeavyRider->chargeTimer]);
1252
++HeavyRider->chargeTimer;
1253
}
1254
}
1255
else {
1256
RSDK.PlaySfx(HeavyRider->sfxLaunch, false, 255);
1257
self->timer = 30;
1258
self->state = HeavyRider_StateJimmy_RevRelease;
1259
1260
if (self->direction == FLIP_NONE)
1261
self->groundVel = 0x40000;
1262
else
1263
self->groundVel = -0x40000;
1264
}
1265
}
1266
1267
#if GAME_INCLUDE_EDITOR
1268
void HeavyRider_EditorDraw(void)
1269
{
1270
RSDK_THIS(HeavyRider);
1271
1272
switch (self->type) {
1273
case HEAVYRIDER_RIDER:
1274
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 0, &self->mainAnimator, true, 0);
1275
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 5, &self->thrustAnimator, true, 0);
1276
RSDK.SetSpriteAnimation(HeavyRider->aniFrames, 7, &self->spikeBallAnimator, true, 0);
1277
RSDK.SetSpriteAnimation(-1, 0, &self->fireballAnimator, true, 0);
1278
1279
self->updateRange.x = 0x800000;
1280
self->updateRange.y = 0x800000;
1281
1282
HeavyRider->spikeBallAngle = 0x80;
1283
HeavyRider->spikeBallState = HEAVYRIDER_SPIKEBALL_SWINGING;
1284
HeavyRider->spawnDelay = 16;
1285
HeavyRider->spawnFireballs = false;
1286
HeavyRider->startY = self->position.y;
1287
HeavyRider->curAttack = HEAVYRIDER_ATK_RIDING_SCREENBOUNDS;
1288
HeavyRider->wheelExtendState = HEAVYRIDER_WHEEL_NONE;
1289
HeavyRider->wheelLength = 0;
1290
1291
self->stateDraw = HeavyRider_Draw_Boss;
1292
break;
1293
1294
case HEAVYRIDER_PLANESWITCH:
1295
RSDK.SetSpriteAnimation(PlaneSwitch->aniFrames, 0, &self->mainAnimator, true, 0);
1296
1297
self->updateRange.x = 0x200000;
1298
self->updateRange.y = (self->size + 0x400) << 11;
1299
self->stateDraw = HeavyRider_Draw_PlaneSwitch;
1300
break;
1301
1302
case HEAVYRIDER_FORCECHARGE_LEFT:
1303
case HEAVYRIDER_FORCECHARGE_RIGHT:
1304
1305
RSDK.SetSpriteAnimation(PlaneSwitch->aniFrames, 0, &self->mainAnimator, true, ((self->type - 2) >> 1) + 4);
1306
1307
self->updateRange.x = 0x200000;
1308
self->updateRange.y = 0x200000;
1309
self->state = HeavyRider_State_ChargeTrigger;
1310
self->stateDraw = HeavyRider_Draw_Simple;
1311
break;
1312
1313
default: break;
1314
}
1315
1316
StateMachine_Run(self->stateDraw);
1317
1318
if (self->type == HEAVYRIDER_RIDER && showGizmos()) {
1319
RSDK_DRAWING_OVERLAY(true);
1320
DrawHelpers_DrawArenaBounds(-WIDE_SCR_XSIZE, -SCREEN_YSIZE, WIDE_SCR_XSIZE, SCREEN_YSIZE, 1 | 0 | 4 | 0, 0x00C0F0);
1321
RSDK_DRAWING_OVERLAY(false);
1322
}
1323
}
1324
1325
void HeavyRider_EditorLoad(void)
1326
{
1327
HeavyRider->aniFrames = RSDK.LoadSpriteAnimation("LRZ3/HeavyRider.bin", SCOPE_STAGE);
1328
1329
// I dont want clang format to do its magic here since I want a specific formatting so
1330
// clang-format off
1331
RSDK_ACTIVE_VAR(HeavyRider, flags);
1332
RSDK_ENUM_VAR("Plane R: A, Draw Group R: Low, Plane L: A, Draw Group L: Low ", PLANESWITCH_PLANEA_RIGHT | PLANESWITCH_LOWLAYER_RIGHT | PLANESWITCH_PLANEA_LEFT | PLANESWITCH_LOWLAYER_LEFT);
1333
RSDK_ENUM_VAR("Plane R: A, Draw Group R: Low, Plane L: A, Draw Group L: High", PLANESWITCH_PLANEA_RIGHT | PLANESWITCH_LOWLAYER_RIGHT | PLANESWITCH_PLANEA_LEFT | PLANESWITCH_HIGHLAYER_LEFT);
1334
RSDK_ENUM_VAR("Plane R: A, Draw Group R: Low, Plane L: B, Draw Group L: Low ", PLANESWITCH_PLANEA_RIGHT | PLANESWITCH_LOWLAYER_RIGHT | PLANESWITCH_PLANEB_LEFT | PLANESWITCH_LOWLAYER_LEFT);
1335
RSDK_ENUM_VAR("Plane R: A, Draw Group R: Low, Plane L: B, Draw Group L: High", PLANESWITCH_PLANEA_RIGHT | PLANESWITCH_LOWLAYER_RIGHT | PLANESWITCH_PLANEB_LEFT | PLANESWITCH_HIGHLAYER_LEFT);
1336
RSDK_ENUM_VAR("Plane R: A, Draw Group R: High, Plane L: A, Draw Group L: Low ", PLANESWITCH_PLANEA_RIGHT | PLANESWITCH_HIGHLAYER_RIGHT | PLANESWITCH_PLANEA_LEFT | PLANESWITCH_LOWLAYER_LEFT);
1337
RSDK_ENUM_VAR("Plane R: A, Draw Group R: High, Plane L: A, Draw Group L: High", PLANESWITCH_PLANEA_RIGHT | PLANESWITCH_HIGHLAYER_RIGHT | PLANESWITCH_PLANEA_LEFT | PLANESWITCH_HIGHLAYER_LEFT);
1338
RSDK_ENUM_VAR("Plane R: A, Draw Group R: High, Plane L: B, Draw Group L: Low ", PLANESWITCH_PLANEA_RIGHT | PLANESWITCH_HIGHLAYER_RIGHT | PLANESWITCH_PLANEB_LEFT | PLANESWITCH_LOWLAYER_LEFT);
1339
RSDK_ENUM_VAR("Plane R: A, Draw Group R: High, Plane L: B, Draw Group L: High", PLANESWITCH_PLANEA_RIGHT | PLANESWITCH_HIGHLAYER_RIGHT | PLANESWITCH_PLANEB_LEFT | PLANESWITCH_HIGHLAYER_LEFT);
1340
RSDK_ENUM_VAR("Plane R: B, Draw Group R: Low, Plane L: A, Draw Group L: Low ", PLANESWITCH_PLANEB_RIGHT | PLANESWITCH_LOWLAYER_RIGHT | PLANESWITCH_PLANEA_LEFT | PLANESWITCH_LOWLAYER_LEFT);
1341
RSDK_ENUM_VAR("Plane R: B, Draw Group R: Low, Plane L: A, Draw Group L: High", PLANESWITCH_PLANEB_RIGHT | PLANESWITCH_LOWLAYER_RIGHT | PLANESWITCH_PLANEA_LEFT | PLANESWITCH_HIGHLAYER_LEFT);
1342
RSDK_ENUM_VAR("Plane R: B, Draw Group R: Low, Plane L: B, Draw Group L: Low ", PLANESWITCH_PLANEB_RIGHT | PLANESWITCH_LOWLAYER_RIGHT | PLANESWITCH_PLANEB_LEFT | PLANESWITCH_LOWLAYER_LEFT);
1343
RSDK_ENUM_VAR("Plane R: B, Draw Group R: Low, Plane L: B, Draw Group L: High", PLANESWITCH_PLANEB_RIGHT | PLANESWITCH_LOWLAYER_RIGHT | PLANESWITCH_PLANEB_LEFT | PLANESWITCH_HIGHLAYER_LEFT);
1344
RSDK_ENUM_VAR("Plane R: B, Draw Group R: High, Plane L: A, Draw Group L: Low ", PLANESWITCH_PLANEB_RIGHT | PLANESWITCH_HIGHLAYER_RIGHT | PLANESWITCH_PLANEA_LEFT | PLANESWITCH_LOWLAYER_LEFT);
1345
RSDK_ENUM_VAR("Plane R: B, Draw Group R: High, Plane L: A, Draw Group L: High", PLANESWITCH_PLANEB_RIGHT | PLANESWITCH_HIGHLAYER_RIGHT | PLANESWITCH_PLANEA_LEFT | PLANESWITCH_HIGHLAYER_LEFT);
1346
RSDK_ENUM_VAR("Plane R: B, Draw Group R: High, Plane L: B, Draw Group L: Low ", PLANESWITCH_PLANEB_RIGHT | PLANESWITCH_HIGHLAYER_RIGHT | PLANESWITCH_PLANEB_LEFT | PLANESWITCH_LOWLAYER_LEFT);
1347
RSDK_ENUM_VAR("Plane R: B, Draw Group R: High, Plane L: B, Draw Group L: High", PLANESWITCH_PLANEB_RIGHT | PLANESWITCH_HIGHLAYER_RIGHT | PLANESWITCH_PLANEB_LEFT | PLANESWITCH_HIGHLAYER_LEFT);
1348
// clang-format on
1349
1350
RSDK_ACTIVE_VAR(HeavyRider, type);
1351
RSDK_ENUM_VAR("Rider", HEAVYRIDER_RIDER);
1352
RSDK_ENUM_VAR("PlaneSwitch", HEAVYRIDER_PLANESWITCH);
1353
RSDK_ENUM_VAR("Charge Trigger (Left)", HEAVYRIDER_FORCECHARGE_LEFT);
1354
RSDK_ENUM_VAR("Charge Trigger (Right)", HEAVYRIDER_FORCECHARGE_RIGHT);
1355
}
1356
#endif
1357
1358
void HeavyRider_Serialize(void)
1359
{
1360
RSDK_EDITABLE_VAR(HeavyRider, VAR_UINT8, type);
1361
RSDK_EDITABLE_VAR(HeavyRider, VAR_ENUM, flags);
1362
RSDK_EDITABLE_VAR(HeavyRider, VAR_ENUM, size);
1363
RSDK_EDITABLE_VAR(HeavyRider, VAR_BOOL, affectPlayer);
1364
}
1365
1366
1367