Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-CD-2011-Script-Decompilation
Path: blob/main/Scripts/R7/MetalSonic.txt
1319 views
1
//----------------Sonic CD Metal Sonic Script-----------------//
2
//--------Scripted by Christian Whitehead 'The Taxman'--------//
3
//-------Unpacked By Rubberduckycooly's Script Unpacker-------//
4
5
// Aliases
6
#alias Object.Value0 : Object.Timer
7
8
#alias Object.Value1 : Object.XVelocity
9
#alias Object.Value2 : Object.YVelocity
10
11
// For the extra sprites associated with Metal Sonic, like his lightning effects
12
#alias Object.Value3 : Object.AccessoryAnimation
13
#alias Object.Value4 : Object.AccessoryFrame
14
15
// State Aliases
16
#alias 0 : METALSONIC_WAITING
17
#alias 1 : METALSONIC_TURNRIGHT
18
#alias 2 : METALSONIC_STARTUP
19
#alias 3 : METALSONIC_ADVANCEMAIN
20
#alias 4 : METALSONIC_CHARGEUP
21
#alias 5 : METALSONIC_ELETRICSHIELD
22
#alias 6 : METALSONIC_DASHING
23
#alias 7 : METALSONIC_TAUNTING
24
#alias 8 : METALSONIC_DEFEATED
25
26
// Accessory Aliases, to be set to Object.AccessoryAnimation
27
#alias 0 : ACCESSORY_NONE
28
#alias 1 : ACCESSORY_CHARGE1
29
#alias 2 : ACCESSORY_CHARGE2
30
#alias 3 : ACCESSORY_CHARGE3
31
#alias 4 : ACCESSORY_LIGHTNING
32
33
// Metal Sonic has an entire animation file, these aliases correspond to animations in there
34
#alias 0 : ANI_STANDING
35
#alias 1 : ANI_TAUNTING
36
#alias 2 : ANI_TURNING
37
#alias 3 : ANI_HOVERING
38
#alias 4 : ANI_HOVERINGFAST
39
#alias 5 : ANI_ELECTRIFIED
40
#alias 6 : ANI_DASHING1
41
#alias 7 : ANI_DASHING2
42
#alias 8 : ANI_DEFEATED
43
#alias 9 : ANI_CHARGING
44
45
// If you're wondering what Metal Sonic's SpriteFrames are then, it's for his effects like lightning and such
46
47
// Vertical Door States
48
#alias 2 : VERTICALDOOR_END_CLOSING
49
#alias 4 : VERTICALDOOR_END_CLOSING_METAL
50
#alias 6 : VERTICALDOOR_END_CLOSED_SONIC
51
52
// Player Aliases
53
#alias 0 :PLAYER_SONIC_A
54
55
// Collision Side Aliases
56
#alias 0 : CSIDE_FLOOR
57
58
// Global SFX Aliases
59
#alias 22 : SFX_G_EXPLOSION
60
61
// Stage SFX Aliases
62
#alias 4 : SFX_S_MSCHARGE
63
#alias 5 : SFX_S_MSELECTRIC
64
#alias 6 : SFX_S_MSJET
65
66
// Priority Aliases
67
#alias 1 : PRIORITY_ACTIVE
68
69
70
// Function declarations
71
#function MetalSonic_FollowGround
72
73
74
function MetalSonic_FollowGround
75
76
// Move Metal Sonic 32 pixels up to help him follow the ground
77
Object.YPos -= 0x200000
78
79
ObjectTileGrip(CSIDE_FLOOR, 0, 20, 0)
80
if CheckResult == false
81
82
// Metal Sonic's in the air, move him 16 pixels down and try again
83
Object.YPos += 0x100000
84
85
ObjectTileGrip(CSIDE_FLOOR, 0, 20, 0)
86
if CheckResult == false
87
88
// He's still airborne even after moving him down before,
89
// Move him even further down and try again
90
Object.YPos += 0x100000
91
92
ObjectTileGrip(CSIDE_FLOOR, 0, 20, 0)
93
end if
94
end if
95
96
end function
97
98
99
sub ObjectMain
100
switch Object.State
101
case METALSONIC_WAITING
102
if Object.Animation == ANI_STANDING
103
if Player.JumpPress == true
104
// Player's goofing around, go ahead and taunt them for two seconds
105
Object.Timer = 120
106
Object.Animation = ANI_TAUNTING
107
end if
108
else // Object.Animation == ANI_TAUNTING
109
if Object.Timer > 0
110
Object.Timer--
111
else
112
Object.Animation = ANI_STANDING
113
end if
114
end if
115
break
116
117
case METALSONIC_TURNRIGHT
118
// (He is turning to our right btw, not his right)
119
120
if Object.Timer < 140
121
Object.Timer++
122
else
123
// From this point on make Metal Sonic always active, as the player may overtake it during the race and put it out of normal bounds
124
Object.Priority = PRIORITY_ACTIVE
125
126
// Get ready...
127
Object.Timer = 0
128
Object.AccessoryAnimation = ACCESSORY_CHARGE1
129
Object.AccessoryFrame = 0
130
Object.State++
131
end if
132
break
133
134
case METALSONIC_STARTUP
135
if Object.Timer < 204
136
Object.Timer++
137
else
138
// And take off, at the speed of sound! (4 pixels per frame, to be exact!)
139
140
Object.Timer = 0
141
Object.AccessoryAnimation = ACCESSORY_CHARGE2
142
Object.Animation = ANI_HOVERINGFAST
143
Object.XVelocity = 0x40000
144
145
// Reset the achievement value
146
Player.HeavyMetalFlag = true
147
148
Object.State++
149
end if
150
break
151
152
case METALSONIC_ADVANCEMAIN
153
// (Object [-2] is the final vertical door at the end of the race)
154
TempValue0 = Object[-2].XPos
155
TempValue0 -= 0x7000000
156
157
// Is the final door farther than 1792 pixels from Metal Sonic?
158
if Object.XPos < TempValue0
159
160
// Go at a speed depending on how far the player is
161
TempValue0 = Object.XPos
162
TempValue0 -= Player.XPos
163
TempValue0 >>= 6
164
Object.XVelocity = 0x40000
165
Object.XVelocity -= TempValue0
166
167
// Minimum speed of 2 pixels per frame
168
if Object.XVelocity < 0x20000
169
Object.XVelocity = 0x20000
170
end if
171
172
// Maximum speed of 6 pixels per frame
173
if Object.XVelocity > 0x60000
174
Object.XVelocity = 0x60000
175
end if
176
177
// Threshold for the 3rd charge level animation is 3.75 pixels per frame
178
if Object.XVelocity < 0x3C000
179
Object.AccessoryAnimation = ACCESSORY_CHARGE2
180
Object.Animation = ANI_HOVERING
181
else
182
Object.AccessoryAnimation = ACCESSORY_CHARGE3
183
Object.Animation = ANI_HOVERINGFAST
184
end if
185
186
if Object.Timer < 180
187
Object.Timer++
188
else
189
// Start attacking
190
Object.Animation = ANI_CHARGING
191
Object.Timer = 0
192
Object.AccessoryAnimation = ACCESSORY_CHARGE1
193
Object.State++
194
PlayStageSfx(SFX_S_MSCHARGE, false)
195
end if
196
else
197
// Metal Sonic is within 1792 pixels of the door
198
199
// Go at a speed depending on how far the player is
200
TempValue0 = Object.XPos
201
TempValue0 -= Player.XPos
202
TempValue0 >>= 6
203
Object.XVelocity = 0x40000
204
Object.XVelocity -= TempValue0
205
206
// Minimum speed of 2 pixels per frame
207
if Object.XVelocity < 0x20000
208
Object.XVelocity = 0x20000
209
end if
210
211
// Maximum speed of 6 pixels per frame
212
if Object.XVelocity > 0x60000
213
Object.XVelocity = 0x60000
214
end if
215
216
// Threshold for the 3rd charge level animation is 3.75 pixels per frame
217
if Object.XVelocity < 0x3C000
218
Object.AccessoryAnimation = ACCESSORY_CHARGE2
219
Object.Animation = ANI_HOVERING
220
else
221
Object.AccessoryAnimation = ACCESSORY_CHARGE3
222
Object.Animation = ANI_HOVERINGFAST
223
end if
224
225
// Removed code here so that Metal doesn't switch states while near the door
226
end if
227
break
228
229
case METALSONIC_CHARGEUP
230
if Object.Timer < 60
231
Object.Timer++
232
else
233
Object.Timer = 0
234
if Player.XPos > Object.XPos
235
// If the player's ahead of Metal Sonic then we gotta catch up, start a Super Dash!
236
237
Object.State = METALSONIC_DASHING
238
Object.Animation = ANI_DASHING1
239
Object.AccessoryAnimation = ACCESSORY_NONE
240
Object.AccessoryFrame = 0
241
PlayStageSfx(SFX_S_MSJET, false)
242
243
#platform: Use_Haptics
244
// and play a super dash-esque motion as well, even if the player probably doesn't even see Metal Sonic...
245
HapticEffect(55, 0, 0, 0)
246
#endplatform
247
248
else
249
// The player's behind Metal Sonic so we don't want to run too far, just initiate the Eletric Shield instead
250
Object.State = METALSONIC_ELETRICSHIELD
251
252
// Slowing down to a speed of 2 pixels per frame
253
Object.XVelocity = 0x20000
254
Object.Animation = ANI_ELECTRIFIED
255
Object.AccessoryAnimation = ACCESSORY_LIGHTNING
256
Object.AccessoryFrame = 0
257
PlayStageSfx(SFX_S_MSELECTRIC, false)
258
259
#platform: Use_Haptics
260
HapticEffect(60, 0, 0, 0)
261
#endplatform
262
263
end if
264
end if
265
break
266
267
case METALSONIC_ELETRICSHIELD
268
if Object.Timer < 180
269
Object.Timer++
270
271
TempValue0 = Object[-1].XPos
272
TempValue0 += 0x400000
273
274
// See if Metal Sonic is past 64 pixels from the starting door
275
if Object.XPos < TempValue0
276
Object.State = METALSONIC_DASHING
277
Object.Timer = 60
278
Object.Animation = ANI_DASHING2
279
Object.AccessoryAnimation = ACCESSORY_NONE
280
Object.AccessoryFrame = 0
281
PlayStageSfx(SFX_S_MSJET, false)
282
283
#platform: Use_Haptics
284
HapticEffect(55, 0, 0, 0)
285
#endplatform
286
287
end if
288
else
289
Object.Timer = 0
290
Object.State = METALSONIC_ADVANCEMAIN
291
Object.AccessoryFrame = 0
292
end if
293
break
294
295
case METALSONIC_DASHING
296
Object.XVelocity += 0x800
297
if Object.XVelocity > 0x80000
298
Object.XVelocity = 0x80000
299
end if
300
301
if Object.Timer < 180
302
Object.Timer++
303
if Object.Timer == 10
304
Object.Animation = ANI_DASHING2
305
end if
306
else
307
Object.Timer = 0
308
Object.State = METALSONIC_ADVANCEMAIN
309
end if
310
break
311
312
case METALSONIC_TAUNTING
313
// This State is used if Metal Sonic passes the final door before Sonic does
314
315
// Wait for the Player to die, then start taunting them
316
if Player.Animation == ANI_DYING
317
Object.Animation = ANI_TAUNTING
318
end if
319
break
320
321
case METALSONIC_DEFEATED
322
// This state is used for Metal Sonic after being killed with Robotnik's laser
323
324
Object.YVelocity += 0x3800
325
Object.YPos += Object.YVelocity
326
327
if Object.YVelocity > 0x100000
328
ResetObjectEntity(Object.EntityNo, TypeName[Blank Object], 0, 0, 0)
329
330
#platform: Use_Origins
331
// Some new code for Origins's Boss Rush
332
333
// Let the game know we've finished the Boss
334
// -> This code also exists in the Amy 1 Object, though that doesn't have any effect since this code is reached first
335
game.callbackParam0 = true
336
EngineCallback(NOTIFY_BOSS_END)
337
338
if game.playMode == BOOT_PLAYMODE_BOSSRUSH
339
// With how transitions in Boss Rush work, just stop the music here with no fade or anything
340
341
StopMusic()
342
end if
343
#endplatform
344
345
end if
346
break
347
348
end switch
349
350
if Object.XVelocity > 0
351
352
// Object[-1] is the first door in the race
353
TempValue0 = Object[-1].XPos
354
TempValue0 += 0x400000
355
356
// Make sure Metal Sonic is always at least 64 pixels past the first door
357
if Object.XPos < TempValue0
358
Object.XPos = TempValue0
359
end if
360
361
// At higher speeds, we want to be more weary to avoid Robotnik's diabolical traps...
362
if Object.XVelocity > 0x30000
363
TempValue0 = Object.XVelocity
364
TempValue0 -= 0x30000
365
366
Object.XPos += 0x30000
367
CallFunction(MetalSonic_FollowGround)
368
369
Object.XPos += TempValue0
370
CallFunction(MetalSonic_FollowGround)
371
else
372
Object.XPos += Object.XVelocity
373
CallFunction(MetalSonic_FollowGround)
374
end if
375
376
if CheckResult == true
377
// If on the ground, reset Metal Sonic's Y Velocity
378
Object.YVelocity = 0
379
else
380
Object.YVelocity += 0x3800
381
Object.YPos += Object.YVelocity
382
end if
383
384
// Object [-2] is the final vertical door at the end of the race
385
switch Object[-2].State
386
case VERTICALDOOR_END_CLOSING
387
case VERTICALDOOR_END_CLOSED_SONIC
388
// Door in its closed state, meaning Metal Sonic lost and Sonic won
389
390
if Player.HeavyMetalFlag == true
391
if Stage.PlayerListPos == PLAYER_SONIC_A
392
// Player managed to get through the fight without getting hit, give them the Heavy Metal achievment
393
SetAchievement(6, 100)
394
end if
395
end if
396
397
TempValue0 = Object[-2].XPos
398
TempValue0 -= 0x1E0000
399
if Object.XPos > TempValue0
400
Object.XPos = TempValue0
401
Object.XVelocity = 0
402
Object.YVelocity = -0x68000
403
404
Object.AccessoryAnimation = ACCESSORY_NONE
405
Object.Animation = ANI_DEFEATED
406
407
Object.State = METALSONIC_DEFEATED
408
CreateTempObject(TypeName[Explosion], 0, Object.XPos, Object.YPos)
409
410
// Create some Debris, with randomised properties
411
TempValue0 = 0
412
TempValue1 = 4
413
while TempValue0 < 8
414
CreateTempObject(TypeName[Debris], TempValue1, Object.XPos, Object.YPos)
415
Rand(Object[TempObjectPos].XVelocity, 4)
416
Object[TempObjectPos].YVelocity++
417
Object[TempObjectPos].XVelocity <<= 16
418
FlipSign(Object[TempObjectPos].XVelocity)
419
Rand(Object[TempObjectPos].YVelocity, 3)
420
Object[TempObjectPos].YVelocity += 2
421
Object[TempObjectPos].YVelocity <<= 16
422
FlipSign(Object[TempObjectPos].YVelocity)
423
TempValue0++
424
TempValue1++
425
if TempValue1 > 8
426
TempValue1 = 4
427
end if
428
loop
429
430
PlaySfx(SFX_G_EXPLOSION, false)
431
432
#platform: Use_Haptics
433
HapticEffect(90, 0, 0, 0)
434
#endplatform
435
436
end if
437
break
438
439
case VERTICALDOOR_END_CLOSING_METAL
440
TempValue0 = Object[-2].XPos
441
TempValue0 += 0x240000
442
if Object.XPos > TempValue0
443
Object.XPos = TempValue0
444
Object.XVelocity = 0
445
Object.AccessoryAnimation = ACCESSORY_NONE
446
Object.Animation = ANI_STANDING
447
Object.State = METALSONIC_TAUNTING
448
end if
449
break
450
451
end switch
452
453
end if
454
455
ProcessAnimation()
456
end sub
457
458
459
sub ObjectPlayerInteraction
460
switch Object.Animation
461
case ANI_ELECTRIFIED
462
case ANI_DASHING2
463
// Metal Sonic is in a sparking animation, harm the player if they make contact
464
PlayerObjectCollision(C_TOUCH, -16, -12, 16, 12)
465
if CheckResult == true
466
CallFunction(Player_Hit)
467
468
// Now that the player's been hit, the achievement is unobtainable
469
Player.HeavyMetalFlag = false
470
end if
471
472
// (No break used here since there's nothing following)
473
474
end switch
475
476
end sub
477
478
479
sub ObjectDraw
480
// First, draw Metal Sonic's "accessory" (of sorts) behind him
481
switch Object.AccessoryAnimation
482
483
// ACCESSORY_NONE is an unhandled case since it's supposed to show nothing
484
485
case ACCESSORY_CHARGE1
486
TempValue0 = Object.AccessoryFrame
487
TempValue0 >>= 1
488
DrawSprite(TempValue0)
489
Object.AccessoryFrame++
490
Object.AccessoryFrame &= 7
491
break
492
493
case ACCESSORY_CHARGE2
494
TempValue0 = Object.AccessoryFrame
495
TempValue0 >>= 1
496
TempValue0 += 4
497
DrawSprite(TempValue0)
498
Object.AccessoryFrame++
499
Object.AccessoryFrame &= 7
500
break
501
502
case ACCESSORY_CHARGE3
503
TempValue0 = Object.AccessoryFrame
504
TempValue0 >>= 1
505
TempValue0 += 8
506
DrawSprite(TempValue0)
507
Object.AccessoryFrame++
508
Object.AccessoryFrame &= 7
509
break
510
511
case ACCESSORY_LIGHTNING
512
TempValue0 = Object.AccessoryFrame
513
TempValue0 += 12
514
DrawSprite(TempValue0)
515
Object.AccessoryFrame++
516
Object.AccessoryFrame %= 10
517
break
518
519
end switch
520
521
// And now draw Metal Sonic himself, notably done here so he appears on top of these other sprites
522
DrawObjectAnimation()
523
524
end sub
525
526
527
sub ObjectStartup
528
529
LoadSpriteSheet("R7/Objects3.gif")
530
531
LoadAnimation("MetalSonic.Ani")
532
533
// 0-3 - Thruster Frames Set 1
534
SpriteFrame(0, 0, 0, 0, 1, 83)
535
SpriteFrame(-12, 3, 16, 16, 1, 83)
536
SpriteFrame(0, 0, 0, 0, 1, 83)
537
SpriteFrame(-12, 3, 16, 16, 18, 83)
538
539
// 4-7 - Thruster Frames Set 2
540
SpriteFrame(0, 0, 0, 0, 1, 83)
541
SpriteFrame(-14, -8, 16, 16, 18, 83)
542
SpriteFrame(0, 0, 0, 0, 1, 83)
543
SpriteFrame(-18, -12, 24, 24, 1, 100)
544
545
// 8-11 - Thruster Frames Set 3
546
SpriteFrame(0, 0, 0, 0, 1, 83)
547
SpriteFrame(-18, -12, 24, 24, 1, 100)
548
SpriteFrame(0, 0, 0, 0, 1, 83)
549
SpriteFrame(-22, -16, 32, 32, 1, 125)
550
551
// 12-16 - Static Charge Shield Frames
552
SpriteFrame(-24, -28, 48, 48, 150, 75)
553
SpriteFrame(-24, -28, 48, 48, 150, 75)
554
SpriteFrame(-24, -28, 48, 48, 150, 75)
555
SpriteFrame(-24, -28, 48, 48, 150, 75)
556
SpriteFrame(0, 0, 0, 0, 1, 83)
557
SpriteFrame(-24, -28, 48, 48, 199, 75)
558
SpriteFrame(-24, -28, 48, 48, 199, 75)
559
SpriteFrame(-24, -28, 48, 48, 199, 75)
560
SpriteFrame(-24, -28, 48, 48, 199, 75)
561
SpriteFrame(0, 0, 0, 0, 1, 83)
562
563
ArrayPos0 = 32
564
while ArrayPos0 < 1056
565
if Object[ArrayPos0].Type == TypeName[Metal Sonic]
566
567
// Store Metal Sonic's EntityNo to the global variable for it
568
// -> It's used by Break Spikes to know when they should break
569
MetalSonic_EntityNo = ArrayPos0
570
571
end if
572
573
ArrayPos0++
574
loop
575
576
end sub
577
578
579
// ========================
580
// Editor Subs
581
// ========================
582
583
sub RSDKDraw
584
DrawSprite(0)
585
end sub
586
587
588
sub RSDKLoad
589
LoadSpriteSheet("R7/Objects3.gif")
590
SpriteFrame(-20, -20, 40, 40, 83, 1) // Pose for the fans!
591
592
SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")
593
end sub
594
595