Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-CD-2011-Script-Decompilation
Path: blob/main/Scripts/R5/BossPlatform.txt
1319 views
1
//---------------Sonic CD Boss Platform Script----------------//
2
//--------Scripted by Christian Whitehead 'The Taxman'--------//
3
//-------Unpacked By Rubberduckycooly's Script Unpacker-------//
4
5
// Notes:
6
// This Boss Platform is the main controller in this Boss Fight so I'll put everything here
7
8
// The order of Objects in the scene is:
9
// - Boss Spikes
10
// - Boss Bomb
11
// - Bomb Carrier
12
// - Boss Top
13
// - Boss Back Panel
14
// - Eggman
15
// - Boss Platform
16
17
// All the Objects in this Boss Fight are very interconnected, they reach and interact with each other often
18
// As such, it is paramount that they are all setup right, or else the Fight will break quite so!
19
20
// Aliases
21
22
// Value0 servers two distinct purposes across this Object's different states
23
// For clarity, they're just separately named
24
#alias Object.Value0 : Object.Timer
25
#alias Object.Value0 : Object.Bounces
26
27
#alias Object.Value1 : Object.BaseX
28
#alias Object.Value2 : Object.YVelocity
29
#alias Object.Value5 : Object.Grind
30
#alias Object.Value6 : Object.SparksTimer
31
32
// These set of Values are for the Conveyor Belt beneath the Boss
33
// BeltFrame corresponds to one of the palette banks
34
#alias Object.Value3 : Object.BeltSpeed
35
#alias Object.Value4 : Object.BeltTimer
36
#alias Object.Value7 : Object.BeltFrame
37
38
// States
39
#alias 0 : BOSSPLATFORM_IDLE
40
#alias 1 : BOSSPLATFORM_SHAKE
41
#alias 2 : BOSSPLATFORM_FALL_1
42
#alias 3 : BOSSPLATFORM_FIGHT_1
43
#alias 4 : BOSSPLATFORM_FALL_2
44
#alias 5 : BOSSPLATFORM_FIGHT_2
45
#alias 6 : BOSSPLATFORM_FALL_3
46
#alias 7 : BOSSPLATFORM_FIGHT_3
47
#alias 8 : BOSSPLATFORM_FALL_4
48
#alias 9 : BOSSPLATFORM_FIGHT_4
49
#alias 10 : BOSSPLATFORM_EGGFLEE
50
#alias 11 : BOSSPLATFORM_EXPLODE
51
52
// Boss Top Aliases
53
#alias Object.Value1 : Object.BoundsR
54
#alias Object.Value2 : Object.OldBoundsR
55
56
// Boss Spark Aliases
57
#alias Object.Value1 : Object.XVelocity
58
59
// Bomb Carrier States
60
#alias 3 : BOMBCARRIER_SLIDERIGHT
61
62
// Boss Top States
63
#alias 1 : BOSSTOP_MOVEBOUNDS
64
65
// Boss Spark States
66
#alias 0 : BOSSSPARK_GRIND
67
#alias 1 : BOSSSPARK_LAND
68
69
// Eggman Aliases
70
#alias 0 : EGGMAN_IDLE
71
#alias 2 : EGGMAN_DAMAGED
72
#alias 3 : EGGMAN_PANICK_JUMP
73
#alias 6 : EGGMAN_FLEE
74
75
// Fade Music Property Values
76
#alias 1 : FADEMUSIC_TO_LEVEL
77
78
// Collision Sides
79
#alias 0 : CSIDE_FLOOR
80
81
// Gravity
82
#alias 0 : GRAVITY_GROUND
83
84
// Global SFX
85
#alias 22 : SFX_G_EXPLOSION
86
87
// Stage SFX
88
#alias 3 : SFX_S_BOSSHIT
89
#alias 4 : SFX_S_IMPACT1
90
91
// Ink Effect
92
#alias 2 : INK_ALPHA
93
94
95
// Function declarations
96
#function BossPlatform_Conveyor_Update
97
#function BossPlatform_Conveyor_WindDown
98
#function BossPlatform_SpawnLandingSparks
99
100
function BossPlatform_Conveyor_Update
101
102
if Player.Gravity == GRAVITY_GROUND
103
// The Player's on the Ground, so that means we can push 'em around and all that stuff
104
105
if Player.ObjectInteraction == true
106
if Player.Speed > Object.BeltSpeed
107
// The Player's going faster than the Conveyor Belt, but the Belt's gotta keep up!
108
109
// Increase the Belt's Speed by ~0.02 pixels
110
Object.BeltSpeed += 0x600
111
112
// Cap the Belt Speed to be ~5.81 pixels per frame maximum
113
if Object.BeltSpeed > 0x5D000
114
Object.BeltSpeed = 0x5D000
115
end if
116
else
117
// The Player's going slower than (or the same speed as) the Conveyor Belt
118
119
// Let's help the Player a bit and decelerate at a rate of about 0.02 pixels per frame
120
Object.BeltSpeed -= 0x600
121
122
// Enforce a lower minimum cap of 0.75 pixels per frame
123
if Object.BeltSpeed < 0xC000
124
Object.BeltSpeed = 0xC000
125
end if
126
end if
127
128
// First, set TempValue0 to be the value of a speed of 2 pixels to the left per frame
129
TempValue0 = -0x20000
130
131
// Then, add the Belt's actual speed to it
132
TempValue0 += Object.BeltSpeed
133
134
// Don't wanna become positive...
135
if TempValue0 > 0
136
TempValue0 = 0
137
end if
138
139
// And now compare the Player's speed with Temp0
140
// (Do note, TempValue0 is a speed in the left direction, where values are negative,
141
// so "smaller" values are faster)
142
if Player.Speed < TempValue0
143
// If the Player's going faster than Temp0, enforce a maximum speed
144
145
Player.Speed = TempValue0
146
Player.XVelocity = TempValue0
147
end if
148
149
// And then, y'know, actually act as a Conveyor Belt and push the Player left
150
Player.XPos -= Object.BeltSpeed
151
end if
152
else
153
// The Player's in the Air, slow down the Conveyor belt
154
155
// If the Player is flying, make the Belt decelerate faster
156
if Player.State == Player_State_Fly
157
// Make it decelerate by around 0.031 pixels per frame
158
Object.BeltSpeed -= 0x800
159
else
160
// The Player's just in the air normally, decelerate at a rate of 0.0039 pixels per frame
161
Object.BeltSpeed -= 0x100
162
end if
163
164
// Enforce a minumum speed of 0.75 pixels per frame
165
if Object.BeltSpeed < 0xC000
166
Object.BeltSpeed = 0xC000
167
end if
168
169
// Did the Player press the jump button earlier this frame?
170
// (The Player Object is in slot 0, while this one's all the way
171
// down in the Stage Object list, which is why this can be checked this way)
172
if Player.JumpPress == true
173
174
// Player.JumpStrength is normally a positive number, which is why this needs to be done
175
TempValue0 = Player.JumpStrength
176
FlipSign(TempValue0)
177
178
// If the Player's Y Velocity is equal to their base Jump Strength, then that means
179
// they just jumped this frame
180
// -> There's nothing that needs to be accounted for on behalf of slopes because,
181
// the arena's all just one flat line
182
if Player.YVelocity == TempValue0
183
// Silently reset their Horizontal movement values, in order to make their jumping
184
// more responsive
185
186
Player.XVelocity = 0
187
Player.Speed = 0
188
end if
189
190
end if
191
end if
192
193
// Update the Grinding on the Boss's Platform
194
195
TempValue0 = Object.BeltSpeed
196
197
// Subtract the baseline speed - 0.75 per frame - from it
198
TempValue0 -= 0xC000
199
200
// And then divide the remainder from that to level it down from 0-3
201
TempValue0 /= 0x1B000
202
switch TempValue0
203
case 0
204
// Lowest grind speed...
205
206
Object.BeltTimer++
207
Object.Grind++
208
Object.SparksTimer++
209
210
// The Speed's so low, the Boss isn't even shaking...
211
Object.XPos = Object.BaseX
212
Object[-2].XPos = Object.XPos
213
break
214
215
case 1
216
// Getting faster...
217
218
Object.BeltTimer += 2
219
Object.Grind += 2
220
Object.SparksTimer += 4
221
222
// Get the lowest bit of the global Oscillation value
223
TempValue1 = Oscillation
224
TempValue1 &= 1
225
226
// Shake the boss either a pixel left or back to its neutral position - a 2-pixel movement range
227
if TempValue1 == 1
228
Object.XPos = Object.BaseX
229
Object.XPos -= 0x10000
230
else
231
Object.XPos = Object.BaseX
232
end if
233
234
// And then move the Boss Back Panel to match
235
Object[-2].XPos = Object.XPos
236
break
237
238
case 2
239
case 3
240
// Woah! That's a pretty fast speed!
241
// Cases 2/3 are just combined here for simplicity's sake
242
243
Object.BeltTimer += 4
244
Object.Grind += 4
245
Object.SparksTimer += 8
246
247
// Get the lowest bit of the Oscillation value
248
TempValue1 = Oscillation
249
TempValue1 &= 1
250
251
// From that result, move the Boss a pixel either left or right - a 3-pixel movement range
252
if TempValue1 == 1
253
Object.XPos = Object.BaseX
254
Object.XPos -= 0x10000
255
else
256
Object.XPos = Object.BaseX
257
Object.XPos += 0x10000
258
end if
259
260
// And yup, carry the Boss Back Panel along for the ride too!
261
Object[-2].XPos = Object.XPos
262
break
263
264
end switch
265
266
// Update the Conveyor Belt animation
267
// - This Boss erases the normal Conveyor Belt Object,
268
// which is why this now has to be done here
269
if Object.BeltTimer > 3
270
Object.BeltTimer = 0
271
272
Object.BeltFrame--
273
if Object.BeltFrame < 0
274
Object.BeltFrame = 2
275
end if
276
277
SetActivePalette(Object.BeltFrame, 0, Screen.YSize)
278
end if
279
280
// Enforce Left Bounds
281
282
TempValue0 = Player.CollisionLeft
283
TempValue0 <<= 16
284
TempValue0 += Player.XPos
285
286
// Is the Player behind the Boss Spikes?
287
if TempValue0 < Object[-6].XPos
288
// Move them to be ahead of the Boss Spikes
289
290
Player.XPos = Object[-6].XPos
291
TempValue0 = Player.CollisionLeft
292
TempValue0 <<= 16
293
Player.XPos -= TempValue0
294
end if
295
296
// Enforce Right Bounds
297
298
TempValue0 = Player.CollisionRight
299
TempValue0 <<= 16
300
TempValue0 += Player.XPos
301
302
// Object[-3] is the Boss Top, where the Right bounds are stored
303
TempValue1 = Object[-3].BoundsR
304
305
// Is the Player ahead of the Right Bounds?
306
if TempValue0 > TempValue1
307
Player.XPos = TempValue1
308
309
TempValue0 = Player.CollisionRight
310
TempValue0 <<= 16
311
Player.XPos -= TempValue0
312
313
if Player.State == Player_State_Fly
314
// if the Player's flying, then do some stuff to make sure they don't go too far
315
316
Player.Speed = 0
317
Player.XVelocity = 0
318
end if
319
end if
320
321
end function
322
323
324
function BossPlatform_Conveyor_WindDown
325
// For the most part, this function is just a slimmed version of BossPlatform_Conveyor_Update
326
327
// Slow down the Conveyor Belt, at a rate of 0.0625 pixels per frame
328
Object.BeltSpeed -= 0x1000
329
if Object.BeltSpeed < 0
330
// Nope, don't wanna step into the negatives!
331
Object.BeltSpeed = 0
332
end if
333
334
if Player.Gravity == GRAVITY_GROUND
335
// The Player's on the Ground
336
337
if Player.ObjectInteraction == true
338
TempValue0 = -0x20000
339
TempValue0 += Object.BeltSpeed
340
341
if TempValue0 > 0
342
TempValue0 = 0
343
end if
344
345
if Player.Speed < TempValue0
346
Player.Speed = TempValue0
347
Player.XVelocity = TempValue0
348
end if
349
350
Player.XPos -= Object.BeltSpeed
351
end if
352
else
353
// The Player's in the air
354
355
if Player.JumpPress == true
356
TempValue0 = Player.JumpStrength
357
FlipSign(TempValue0)
358
359
if Player.YVelocity == TempValue0
360
Player.XVelocity = 0
361
Player.Speed = 0
362
end if
363
end if
364
end if
365
366
// Even if the boss is defeated, still update some of the grinding stuff
367
// Just, without all the Boss shaking side of the stuff
368
369
TempValue0 = Object.BeltSpeed
370
TempValue0 /= 0x1B000
371
372
switch TempValue0
373
case 0
374
Object.BeltTimer++
375
Object.Grind++
376
Object.SparksTimer++
377
break
378
379
case 1
380
Object.BeltTimer += 2
381
Object.Grind += 2
382
Object.SparksTimer += 4
383
break
384
385
case 2
386
case 3
387
Object.BeltTimer += 4
388
Object.Grind += 4
389
Object.SparksTimer += 8
390
break
391
392
end switch
393
394
if Object.BeltTimer > 3
395
Object.BeltTimer = 0
396
Object.BeltFrame--
397
if Object.BeltFrame < 0
398
Object.BeltFrame = 2
399
end if
400
401
SetActivePalette(Object.BeltFrame, 0, Screen.YSize)
402
end if
403
404
// Enforce Left Bounds
405
406
TempValue0 = Player.CollisionLeft
407
TempValue0 <<= 16
408
TempValue0 += Player.XPos
409
if TempValue0 < Object[-6].XPos
410
Player.XPos = Object[-6].XPos
411
TempValue0 = Player.CollisionLeft
412
TempValue0 <<= 16
413
Player.XPos -= TempValue0
414
end if
415
416
// No enforcing Right Bounds here, the Object's already quite literally a giant box in its ObjectPlayerInteraction
417
418
end function
419
420
421
function BossPlatform_SpawnLandingSparks
422
423
// As you may have guessed, this Function spawns all the cool Sparks the Boss makes
424
// Preconditions:
425
// - TempValue0 is set to the Y Offset for the Sparks
426
427
CreateTempObject(TypeName[Boss Spark], BOSSSPARK_LAND, Object.XPos, Object.YPos)
428
Object[TempObjectPos].XPos -= 0x100000
429
Object[TempObjectPos].YPos += TempValue0
430
Object[TempObjectPos].XVelocity = -0x10000
431
Object[TempObjectPos].YVelocity = -0x18000
432
433
CreateTempObject(TypeName[Boss Spark], BOSSSPARK_LAND, Object.XPos, Object.YPos)
434
Object[TempObjectPos].XPos += 0x100000
435
Object[TempObjectPos].YPos += TempValue0
436
Object[TempObjectPos].XVelocity = -0x10000
437
Object[TempObjectPos].YVelocity = -0x18000
438
439
TempValue0 += 0x80000
440
441
CreateTempObject(TypeName[Boss Spark], BOSSSPARK_LAND, Object.XPos, Object.YPos)
442
Object[TempObjectPos].XPos -= 0x180000
443
Object[TempObjectPos].YPos += TempValue0
444
Object[TempObjectPos].XVelocity = -0x10000
445
Object[TempObjectPos].YVelocity = -0x18000
446
447
CreateTempObject(TypeName[Boss Spark], BOSSSPARK_LAND, Object.XPos, Object.YPos)
448
Object[TempObjectPos].XPos -= 0x40000
449
Object[TempObjectPos].YPos += TempValue0
450
Object[TempObjectPos].XVelocity = -0x10000
451
Object[TempObjectPos].YVelocity = -0x18000
452
453
CreateTempObject(TypeName[Boss Spark], BOSSSPARK_LAND, Object.XPos, Object.YPos)
454
Object[TempObjectPos].XPos += 0x180000
455
Object[TempObjectPos].YPos += TempValue0
456
Object[TempObjectPos].XVelocity = -0x10000
457
Object[TempObjectPos].YVelocity = -0x18000
458
459
CreateTempObject(TypeName[Boss Spark], BOSSSPARK_LAND, Object.XPos, Object.YPos)
460
Object[TempObjectPos].XPos += 0x40000
461
Object[TempObjectPos].YPos += TempValue0
462
Object[TempObjectPos].XVelocity = -0x10000
463
Object[TempObjectPos].YVelocity = -0x18000
464
465
TempValue0 += 0x80000
466
467
CreateTempObject(TypeName[Boss Spark], BOSSSPARK_LAND, Object.XPos, Object.YPos)
468
Object[TempObjectPos].XPos -= 0x100000
469
Object[TempObjectPos].YPos += TempValue0
470
Object[TempObjectPos].XVelocity = -0x10000
471
Object[TempObjectPos].YVelocity = -0x18000
472
473
CreateTempObject(TypeName[Boss Spark], BOSSSPARK_LAND, Object.XPos, Object.YPos)
474
Object[TempObjectPos].XPos += 0x100000
475
Object[TempObjectPos].YPos += TempValue0
476
Object[TempObjectPos].XVelocity = -0x10000
477
Object[TempObjectPos].YVelocity = -0x18000
478
479
end function
480
481
482
sub ObjectMain
483
484
switch Object.State
485
case BOSSPLATFORM_SHAKE
486
if Object.Timer < 60
487
Object.Timer++
488
489
// Get the lowest bit of the Timer
490
TempValue0 = Object.Timer
491
TempValue0 &= 1
492
493
// Shake a bit, direction depending on what that Bit is
494
if TempValue0 == 1
495
// Move a pixel down
496
Object.YPos += 0x20000
497
else
498
// Move a pixel up
499
Object.YPos -= 0x20000
500
end if
501
else
502
// Start falling
503
504
Object.Timer = 0
505
Object.State = BOSSPLATFORM_FALL_1
506
507
// Make Robotnik go into his shock animation
508
Object[-1].State = EGGMAN_DAMAGED
509
Object[-1].Frame = 0
510
Object[-1].Timer = 0
511
end if
512
513
// Move Robotnik along, to be 28 pixels above the Platform's Y Position
514
Object[-1].YPos = Object.YPos
515
Object[-1].YPos -= 0x1C0000
516
517
// And then move the Boss's Back Panel too
518
Object[-2].YPos = Object.YPos
519
520
// Start up the Conveyor
521
CallFunction(BossPlatform_Conveyor_Update)
522
523
// For now, regardless of the Coveyor's Speed, stay at the base position
524
Object.XPos = Object.BaseX
525
526
// And apply this to the Boss Back Panel as well
527
Object[-2].XPos = Object.BaseX
528
break
529
530
case BOSSPLATFORM_FALL_1
531
532
// Accelerate the falling speed at a rate of about 0.09 pixels per frame
533
Object.YVelocity += 0x1800
534
535
// And then, y'know, do the actual falling
536
Object.YPos += Object.YVelocity
537
538
// Check to see if this Object's hit the ground
539
// (Note the use of 31 for the Y Offset here, it changes for every falling cycle)
540
ObjectTileCollision(CSIDE_FLOOR, 0, 31, 0)
541
542
if CheckResult == true
543
Screen.ShakeY = 4
544
545
PlayStageSfx(SFX_S_IMPACT1, false)
546
547
// Bounce once
548
if Object.Bounces < 1
549
Object.Bounces++
550
551
// Tone the Y Velocity down a bit and turn it right around!
552
Object.YVelocity >>= 1
553
FlipSign(Object.YVelocity)
554
else
555
// Start the first main phase of the Fight
556
557
Object.State = BOSSPLATFORM_FIGHT_1
558
Object[-1].State = EGGMAN_IDLE
559
Object.Bounces = 0
560
Object.Grind = 0
561
end if
562
563
// Spawn Sparks, with an offset of 19 pixels
564
TempValue0 = 0x130000
565
CallFunction(BossPlatform_SpawnLandingSparks)
566
567
#platform: Use_Haptics
568
HapticEffect(97, 0, 0, 0)
569
#endplatform
570
end if
571
572
573
Object[-1].YPos = Object.YPos
574
Object[-1].YPos -= 0x1C0000
575
576
Object[-2].YPos = Object.YPos
577
578
// Update the Conveyor Belt, but...
579
CallFunction(BossPlatform_Conveyor_Update)
580
581
// Revert whatever it does to the Boss's position, as the Boss is still in the air
582
Object.XPos = Object.BaseX
583
Object[-2].XPos = Object.BaseX
584
break
585
586
case BOSSPLATFORM_FIGHT_1
587
// First main phase of the fight
588
589
CallFunction(BossPlatform_Conveyor_Update)
590
591
if Object.Grind > 2399
592
Object.State++
593
end if
594
595
if Object.SparksTimer > 47
596
Object.SparksTimer %= 48
597
598
// Create a Spark, with properties of:
599
// - 24 pixels right from the Boss Platform
600
// - 27 pixels below the Boss Platform
601
// - Starting X Velocity of one pixel a frame to the left
602
CreateTempObject(TypeName[Boss Spark], BOSSSPARK_GRIND, Object.XPos, Object.YPos)
603
Object[TempObjectPos].XPos += 0x180000
604
Object[TempObjectPos].YPos += 0x1B0000
605
Object[TempObjectPos].XVelocity = -0x10000
606
end if
607
break
608
609
case BOSSPLATFORM_FALL_2
610
611
// Falling acceleration speed rate of about 0.09 pixels per frame
612
Object.YVelocity += 0x1800
613
614
Object.YPos += Object.YVelocity
615
616
// Check to see if the Boss Platform's hit the ground
617
// Note that the Y Offset is 23 here, shorter than the 31 from last time
618
ObjectTileCollision(CSIDE_FLOOR, 0, 23, 0)
619
620
if CheckResult == true
621
Screen.ShakeY = 4
622
623
PlayStageSfx(SFX_S_IMPACT1, false)
624
625
// Bounce once when initially hitting the ground
626
if Object.Bounces < 1
627
Object.Bounces++
628
629
// Lower Velocity it turn it around
630
Object.YVelocity >>= 1
631
FlipSign(Object.YVelocity)
632
else
633
Object.State = BOSSPLATFORM_FIGHT_2
634
Object.Bounces = 0
635
Object.Grind = 0
636
end if
637
638
// Spawn landing Sparks, with an offset of 11 pixels
639
TempValue0 = 0xB0000
640
CallFunction(BossPlatform_SpawnLandingSparks)
641
642
#platform: Use_Haptics
643
HapticEffect(97, 0, 0, 0)
644
#endplatform
645
end if
646
647
// Move Eggman to match this Object's position, 28 pixels above
648
Object[-1].YPos = Object.YPos
649
Object[-1].YPos -= 0x1C0000
650
651
// And move the Boss Back Panel along as well
652
Object[-2].YPos = Object.YPos
653
654
// Update the Conveyor underneat the Boss, even if the Boss may not be on it
655
// -> With this, however, the Boss's Base Position isn't restored afterwards
656
// so the Boss may still shake slightly horizontally while in the air
657
CallFunction(BossPlatform_Conveyor_Update)
658
break
659
660
case BOSSPLATFORM_FIGHT_2
661
CallFunction(BossPlatform_Conveyor_Update)
662
663
if Object.Grind > 2399
664
Object.State++
665
end if
666
667
if Object.SparksTimer > 47
668
Object.SparksTimer %= 48
669
670
// Create a Boss Spark, with values of:
671
// - 24 pixels right from the Boss's Position
672
// - 19 pixels below the Boss's Position
673
// - X Velocity of 1 pixel left per frame
674
CreateTempObject(TypeName[Boss Spark], BOSSSPARK_GRIND, Object.XPos, Object.YPos)
675
Object[TempObjectPos].XPos += 0x180000
676
Object[TempObjectPos].YPos += 0x130000
677
Object[TempObjectPos].XVelocity = -0x10000
678
end if
679
break
680
681
case BOSSPLATFORM_FALL_3
682
683
// Fall with an acceleration speed of about 0.09 pixels per frame
684
Object.YVelocity += 0x1800
685
686
Object.YPos += Object.YVelocity
687
688
// Check for Floor collision, now with a Y Offset of 15
689
ObjectTileCollision(CSIDE_FLOOR, 0, 15, 0)
690
691
if CheckResult == true
692
Screen.ShakeY = 4
693
694
PlayStageSfx(SFX_S_IMPACT1, false)
695
696
// Bounce a single time upon initially landing
697
if Object.Bounces < 1
698
Object.Bounces++
699
700
Object.YVelocity >>= 1
701
FlipSign(Object.YVelocity)
702
else
703
Object.State = BOSSPLATFORM_FIGHT_3
704
Object.Bounces = 0
705
Object.Grind = 0
706
end if
707
708
// Create landing Sparks, with an offset of 3 pixels this time
709
TempValue0 = 0x30000
710
CallFunction(BossPlatform_SpawnLandingSparks)
711
712
#platform: Use_Haptics
713
HapticEffect(97, 0, 0, 0)
714
#endplatform
715
end if
716
717
// Carry Eggman along, to be 28 pixels above this Platform's Position
718
Object[-1].YPos = Object.YPos
719
Object[-1].YPos -= 0x1C0000
720
721
// And his Back Panel, too
722
Object[-2].YPos = Object.YPos
723
724
CallFunction(BossPlatform_Conveyor_Update)
725
break
726
727
case BOSSPLATFORM_FIGHT_3
728
CallFunction(BossPlatform_Conveyor_Update)
729
730
if Object.Grind > 2399
731
Object.State++
732
Object[-1].State = EGGMAN_PANICK_JUMP
733
Object[-1].Frame = 0
734
Object[-1].Timer = 0
735
end if
736
737
if Object.SparksTimer > 47
738
Object.SparksTimer %= 48
739
740
// Create a Boss Spark Object, with starting values of:
741
// - X Position of 24 pixels right of this Boss Platform
742
// - Y Position of 11 pixels below this Boss Platform
743
// - X Velocity of 1 pixel left per frame
744
CreateTempObject(TypeName[Boss Spark], BOSSSPARK_GRIND, Object.XPos, Object.YPos)
745
Object[TempObjectPos].XPos += 0x180000
746
Object[TempObjectPos].YPos += 0xB0000
747
Object[TempObjectPos].XVelocity = -0x10000
748
end if
749
break
750
751
case BOSSPLATFORM_FALL_4
752
753
// Apply a falling acceleration of roughly 0.09 pixels per frame
754
Object.YVelocity += 0x1800
755
756
Object.YPos += Object.YVelocity
757
758
// Check for Ground Collision, now with an even smaller Y Offset of 7 pixels
759
ObjectTileCollision(CSIDE_FLOOR, 0, 7, 0)
760
761
if CheckResult == true
762
Screen.ShakeY = 4
763
764
PlayStageSfx(SFX_S_IMPACT1, false)
765
766
// Just like every other time, bounce one time upon initially landing
767
if Object.Bounces < 1
768
Object.Bounces++
769
770
// Minimize & flip the Y Velocity
771
Object.YVelocity >>= 1
772
FlipSign(Object.YVelocity)
773
else
774
Object.State = BOSSPLATFORM_FIGHT_4
775
Object.Bounces = 0
776
Object.Grind = 0
777
end if
778
779
// Spawn some Landing Sparks, with an offset of 3 pixels up
780
TempValue0 = -0x30000
781
CallFunction(BossPlatform_SpawnLandingSparks)
782
783
#platform: Use_Haptics
784
HapticEffect(97, 0, 0, 0)
785
#endplatform
786
end if
787
788
// Carry Eggman along, keeping him 28 pixels above this Object's Base Y Position
789
Object[-1].YPos = Object.YPos
790
Object[-1].YPos -= 0x1C0000
791
792
// And then Eggman's control Panel too, he needs something to hold on to!
793
Object[-2].YPos = Object.YPos
794
795
CallFunction(BossPlatform_Conveyor_Update)
796
break
797
798
case BOSSPLATFORM_FIGHT_4
799
// We're in the final strech now!
800
801
CallFunction(BossPlatform_Conveyor_Update)
802
803
if Object.Grind > 2399
804
Object.State++
805
806
// Make Robotnik start running away
807
Object[-1].State = EGGMAN_FLEE
808
Object[-1].Frame = 0
809
Object[-1].Timer = 0
810
811
// Move him to draw ontop of this Boss Platform Object and all its other accessories
812
Object[-1].DrawOrder = 4
813
814
// Move this Object back to its Base Position, and move the Boss Back Panel with it too
815
Object.XPos = Object.BaseX
816
Object[-2].XPos = Object.XPos
817
818
Object.Timer = 0
819
end if
820
821
if Object.SparksTimer > 47
822
Object.SparksTimer %= 48
823
824
// Create a Boss Spark, with properties of:
825
// - 24 pixels left right from this Platform
826
// - 3 pixels below this Platform Object
827
// - Velocity of 1 pixel left per frame
828
CreateTempObject(TypeName[Boss Spark], BOSSSPARK_GRIND, Object.XPos, Object.YPos)
829
Object[TempObjectPos].XPos += 0x180000
830
Object[TempObjectPos].YPos += 0x30000
831
Object[TempObjectPos].XVelocity = -0x10000
832
end if
833
break
834
835
case BOSSPLATFORM_EGGFLEE
836
if Object.Timer == 19
837
Object.Timer = 0
838
TempValue0 = -0x30000
839
CallFunction(BossPlatform_SpawnLandingSparks)
840
end if
841
842
Object.Timer++
843
844
if Object.BeltSpeed > 0
845
// If the Belt's still running, then slow it down
846
847
CallFunction(BossPlatform_Conveyor_WindDown)
848
849
// Restore Stage Bounds, in a way to make the camera pan to the right
850
// -> The full restoring of those bounds is done right below, with the Boss Platform's OldBoundsR
851
Stage.XBoundary2 += 4
852
else
853
854
#platform: Use_Origins
855
// Some addditions for Origins
856
857
// Let the game know that we've "killed" the boss
858
// Poor Robotnik, I hope he's alright...
859
EngineCallback(NOTIFY_KILL_BOSS)
860
861
// Tell HE2 that the boss fight ended
862
game.callbackParam0 = true
863
EngineCallback(NOTIFY_BOSS_END)
864
865
if game.playMode == BOOT_PLAYMODE_BOSSRUSH
866
// In Boss Rush, stop the music since we're getting sent to the next zone now
867
868
StopMusic()
869
end if
870
#endplatform
871
872
// Restore the Stage's Bounds to normal
873
Stage.NewXBoundary2 = Object[-3].OldBoundsR
874
875
Object.State++
876
Object.Timer = 0
877
878
// Both this object and BossTop uses alpha for it's red flashing
879
Object.InkEffect = INK_ALPHA
880
Object[-3].InkEffect = INK_ALPHA
881
882
#platform: Use_Haptics
883
HapticEffect(97, 0, 0, 0)
884
#endplatform
885
end if
886
break
887
888
case BOSSPLATFORM_EXPLODE
889
890
// Oscillate the red flashing of this & the Boss Top's red flashing
891
892
Sin(TempValue0, Object.Timer)
893
894
TempValue0 /= 3
895
if TempValue0 < 0
896
// Stay in the positives here
897
FlipSign(TempValue0)
898
end if
899
900
if TempValue0 > 255
901
// Cap at 255
902
TempValue0 = 255
903
end if
904
905
// Set this and the Boss Top's Alpha to be the same
906
Object.Alpha = TempValue0
907
Object[-3].Alpha = TempValue0
908
909
TempValue0 = Object.Timer
910
TempValue0 &= 127
911
912
if TempValue0 == 0
913
// Create an Explosion, 32 pixels left and 16 pixels above this Object
914
915
CreateTempObject(TypeName[Boss Explosion], 0, Object.XPos, Object.YPos)
916
Object[TempObjectPos].XPos -= 0x200000
917
Object[TempObjectPos].YPos -= 0x100000
918
end if
919
920
if TempValue0 == 32
921
// Create an Explosion, now 16 pixels left from this object
922
923
CreateTempObject(TypeName[Boss Explosion], 0, Object.XPos, Object.YPos)
924
Object[TempObjectPos].XPos -= 0x100000
925
end if
926
927
if TempValue0 == 64
928
// Create an Explosion, this one 32 pixels to the right and 16 pixels above this Object
929
930
CreateTempObject(TypeName[Boss Explosion], 0, Object.XPos, Object.YPos)
931
Object[TempObjectPos].XPos += 0x200000
932
Object[TempObjectPos].YPos -= 0x100000
933
end if
934
935
TempValue0 = Object.Timer
936
TempValue0 &= 31
937
if TempValue0 == 0
938
PlaySfx(SFX_G_EXPLOSION, false)
939
end if
940
941
Object.Timer += 8
942
if Object.Timer > 960
943
Player.Score += 1000
944
CreateTempObject(TypeName[Fade Music], FADEMUSIC_TO_LEVEL, 0, 0)
945
946
// Clear all of the Boss's Objects
947
948
// Let's start with this one - the Boss Platform
949
TempValue0 = Object.EntityNo
950
ResetObjectEntity(TempValue0, TypeName[Blank Object], 0, 0, 0)
951
952
// Then, the Eggman Object
953
TempValue0--
954
ResetObjectEntity(TempValue0, TypeName[Blank Object], 0, 0, 0)
955
956
// Then, the Boss Back Panel Object
957
TempValue0--
958
ResetObjectEntity(TempValue0, TypeName[Blank Object], 0, 0, 0)
959
960
// After that comes the Boss Top Object
961
TempValue0--
962
ResetObjectEntity(TempValue0, TypeName[Blank Object], 0, 0, 0)
963
964
// Then the Bomb Carrier Object
965
TempValue0--
966
ResetObjectEntity(TempValue0, TypeName[Blank Object], 0, 0, 0)
967
968
// And finally, the Boss Bomb Object
969
TempValue0--
970
ResetObjectEntity(TempValue0, TypeName[Blank Object], 0, 0, 0)
971
972
// The Object after all those, the Boss Spikes Object, is left alone
973
end if
974
break
975
976
end switch
977
978
end sub
979
980
981
sub ObjectPlayerInteraction
982
983
if Object.State == BOSSPLATFORM_IDLE
984
// See if the Player's hit the currently static machine
985
986
PlayerObjectCollision(C_TOUCH, -32, -48, 32, 32)
987
988
if CheckResult == true
989
FlipSign(Player.XVelocity)
990
FlipSign(Player.YVelocity)
991
TempValue0 = Player.XVelocity
992
TempValue1 = Player.YVelocity
993
Player.Speed = TempValue0
994
Player.XVelocity = TempValue0
995
Player.YVelocity = TempValue1
996
Object.State = BOSSPLATFORM_SHAKE
997
998
// Set the Object's Base/Origin Position, this needs to be stored as the Object will
999
// slightly shake horizontally during the Boss Fight
1000
Object.BaseX = Object.XPos
1001
1002
// Tell the Boss Top to start moving the stage boundary left
1003
Object[-3].State = BOSSTOP_MOVEBOUNDS
1004
1005
// Made the Bomb Carrier start up, as well
1006
Object[-4].State = BOMBCARRIER_SLIDERIGHT
1007
1008
// Ka-thunk!
1009
PlayStageSfx(SFX_S_BOSSHIT, false)
1010
1011
#platform: Use_Haptics
1012
HapticEffect(97, 0, 0, 0)
1013
#endplatform
1014
1015
#platform: Use_Origins
1016
if Stage.PlayerListPos == PLAYER_KNUCKLES
1017
if Player.Animation == ANI_GLIDING
1018
Player.Animation = ANI_GLIDING_DROP
1019
Player.State = Player_State_GlideDrop
1020
end if
1021
end if
1022
#endplatform
1023
end if
1024
else
1025
// Just act as a box for the Player
1026
// -> All the actual cool, fun stuff is done over in ObjectMain instead
1027
PlayerObjectCollision(C_BOX, -32, -256, 32, 24)
1028
end if
1029
1030
end sub
1031
1032
1033
sub ObjectDraw
1034
1035
// Each State gets its own Drawing routine
1036
// -> For the most part, these are all the same, but with different latter frames for the Boss Platform's bottom
1037
switch Object.State
1038
case BOSSPLATFORM_IDLE
1039
case BOSSPLATFORM_SHAKE
1040
case BOSSPLATFORM_FALL_1
1041
DrawSprite(0)
1042
DrawSprite(1)
1043
break
1044
1045
case BOSSPLATFORM_FIGHT_1
1046
DrawSprite(0)
1047
DrawSprite(2)
1048
break
1049
1050
case BOSSPLATFORM_FALL_2
1051
case BOSSPLATFORM_FIGHT_2
1052
DrawSprite(0)
1053
DrawSprite(3)
1054
break
1055
1056
case BOSSPLATFORM_FALL_3
1057
case BOSSPLATFORM_FIGHT_3
1058
DrawSprite(0)
1059
DrawSprite(4)
1060
break
1061
1062
case BOSSPLATFORM_FALL_4
1063
case BOSSPLATFORM_FIGHT_4
1064
DrawSprite(0)
1065
DrawSprite(5)
1066
break
1067
1068
case BOSSPLATFORM_EGGFLEE
1069
DrawSprite(0)
1070
DrawSprite(5)
1071
1072
// Now that Robotnik's fleeing, he's taking the Control Panel sprite with him,
1073
// so draw our own here
1074
DrawSprite(6)
1075
break
1076
1077
case BOSSPLATFORM_EXPLODE
1078
DrawSprite(0)
1079
DrawSprite(5)
1080
DrawSprite(6)
1081
1082
// Draw the Red Flashing Frame, with an Alpha of whatever Object.Alpha is set to
1083
DrawSpriteFX(7, FX_INK, Object.XPos, Object.YPos)
1084
break
1085
1086
end switch
1087
1088
end sub
1089
1090
1091
sub ObjectStartup
1092
1093
LoadSpriteSheet("R5/Objects2.gif")
1094
1095
// Boss Platform Frames
1096
1097
// Main Boss Platform Frame
1098
SpriteFrame(-32, -48, 64, 48, 1, 50)
1099
1100
// Perfect, Ungrinded Bottom Frame
1101
SpriteFrame(-32, 0, 64, 32, 1, 98)
1102
1103
// Gently Grinded Bottom Frame
1104
SpriteFrame(-32, 0, 64, 32, 1, 131)
1105
1106
// Slightly move Grinded Frame
1107
SpriteFrame(-32, 0, 64, 24, 1, 164)
1108
1109
// Considerably more Grinded Frame
1110
SpriteFrame(-32, 0, 64, 16, 1, 189)
1111
1112
// Heavily Grinded Frame (- there's almost nothing left now!)
1113
SpriteFrame(-32, 0, 64, 8, 1, 206)
1114
1115
// Control Panel Frame (normally part of Eggman's sprite itself, for the most part)
1116
SpriteFrame(-32, -48, 26, 24, 1, 215)
1117
1118
// Flashing Red Boss Platform Frame
1119
SpriteFrame(-32, -48, 64, 56, 75, 50)
1120
1121
end sub
1122
1123
1124
// ========================
1125
// Editor Subs
1126
// ========================
1127
1128
sub RSDKDraw
1129
DrawSprite(0)
1130
end sub
1131
1132
1133
sub RSDKLoad
1134
LoadSpriteSheet("R5/Objects2.gif")
1135
SpriteFrame(-32, -48, 64, 48, 1, 50)
1136
SpriteFrame(-32, 0, 64, 32, 1, 98)
1137
1138
SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")
1139
end sub
1140
1141