Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-1-Sonic-2-2013-Script-Decompilation
Path: blob/master/Sonic 2/Scripts/Ending/EndSetup.txt
1478 views
1
// ----------------------------------
2
// RSDK Project: Sonic 2
3
// Script Description: Ending Setup Object
4
// Script Author: Christian Whitehead/Simon Thomley
5
// Unpacked by Rubberduckycooly's script unpacker
6
// ----------------------------------
7
8
// ========================
9
// Aliases
10
// ========================
11
12
private alias object.value0 : object.timer
13
private alias object.value2 : object.blendAmount
14
private alias object.value3 : object.tornadoTimer
15
// values 4-13 are unused...
16
private alias object.value14 : object.paletteTimer
17
private alias object.value15 : object.bgTowerLightPalIndex
18
private alias object.value16 : object.rainbowLightPalIndex
19
private alias object.value17 : object.chemLiquidPalIndex1
20
private alias object.value18 : object.chemLiquidPalIndex2
21
private alias object.value19 : object.chemLiquidPalIndex3
22
23
private alias object.value20 : object.srcBlendPal
24
25
private alias 0 : ENDSETUP_INIT
26
private alias 1 : ENDSETUP_FADEINIMAGE
27
private alias 2 : ENDSETUP_DISPLAYIMAGE
28
private alias 3 : ENDSETUP_FADEOUTIMAGE
29
private alias 4 : ENDSETUP_ENTERPLAYER
30
private alias 5 : ENDSETUP_PLAYERFALLING
31
private alias 6 : ENDSETUP_SPAWNTORNADO
32
private alias 7 : ENDSETUP_TORNADOSPAWNED
33
34
// Player Aliases
35
private alias object.type : player.type
36
private alias object.state : player.state
37
private alias object.visible : player.visible
38
private alias object.xpos : player.xpos
39
private alias object.ypos : player.ypos
40
private alias object.speed : player.speed
41
private alias object.frame : player.frame
42
private alias object.animation : player.animation
43
private alias object.prevAnimation : player.prevAnimation
44
45
private alias object.value0 : player.rings
46
private alias object.value7 : player.invincibleTimer
47
private alias object.value8 : player.blinkTimer
48
private alias object.value18 : player.sortedDrawOrder
49
50
// Tracks
51
private alias 0 : TRACK_STAGE
52
53
// Super States
54
private alias 1 : SUPERSTATE_SUPER
55
56
57
// ========================
58
// Static Values
59
// ========================
60
61
public value EndingSetup_scrollVelocity.x = 0
62
public value EndingSetup_scrollVelocity.y = 0
63
64
65
// ========================
66
// Tables
67
// ========================
68
69
// All these tables are copies of DEZ's tables
70
private table EndingSetup_bgTowerPalTable
71
0xE00000, 0xC00000, 0xA00000, 0x800000, 0x600000, 0x400000, 0x200000, 0x400000
72
0x600000, 0x800000, 0xA00000, 0xC00000, 0xE00000, 0xE02000, 0xE04000, 0xE02000
73
end table
74
75
private table EndingSetup_blendLightPalTable
76
0x00E000, 0x20C000, 0x40A000, 0x608000, 0x806000, 0xA04000, 0xC02000
77
0xE00000, 0xC00020, 0xA00040, 0x800060, 0x600080, 0x4000A0, 0x2000C0
78
0x0000E0, 0x0020C0, 0x0040A0, 0x006080, 0x008060, 0x00A040, 0x00C020
79
end table
80
81
private table EndingSetup_chemLiquidPalTable
82
0x0040E0, 0x0000C0, 0x0000C0
83
0x0060E0, 0x0020C0, 0x0000C0
84
0x0040E0, 0x0040E0, 0x0000C0
85
0x0020C0, 0x0060E0, 0x0020C0
86
0x0000C0, 0x0040E0, 0x0040C0
87
0x0000C0, 0x0020C0, 0x0040E0
88
0x0000C0, 0x0000C0, 0x0060E0
89
0x0020C0, 0x0000C0, 0x0040E0
90
0x0020E0, 0x0000C0, 0x0020C0
91
end table
92
93
// Unused table, also in CPZ and DEZ
94
// See CPZSetup/DEZSetup for full explanation
95
private table EndingSetup_unusedPalette
96
0x00E000, 0x00A000, 0x006000, 0x002000, 0x000000, 0x000020, 0x000060, 0x0020A0
97
0x0060E0, 0x0020A0, 0x000060, 0x000020, 0x000000, 0x200000, 0x600000, 0xA00000
98
0xE00000, 0xE04000, 0xE00000, 0xA00000, 0x600000, 0x200000, 0x000000, 0x202000
99
0x606000, 0xA0A000, 0xE0E000, 0xA0A000, 0x606000, 0x202000, 0x000000, 0x002000
100
0x006000, 0x00A000
101
end table
102
103
104
// ========================
105
// Events
106
// ========================
107
108
event ObjectUpdate
109
// Update palette cycling
110
// (This is just a duplicate of the DEZ palette cycle code, here so that DEZ will look normal for the short moment it appears)
111
object.paletteTimer++
112
if object.paletteTimer == 8
113
object.paletteTimer = 0
114
115
object.bgTowerLightPalIndex++
116
object.bgTowerLightPalIndex &= 15
117
GetTableValue(temp0, object.bgTowerLightPalIndex, EndingSetup_bgTowerPalTable)
118
SetPaletteEntry(0, 175, temp0)
119
120
object.rainbowLightPalIndex++
121
object.rainbowLightPalIndex %= 21
122
GetTableValue(temp0, object.rainbowLightPalIndex, EndingSetup_blendLightPalTable)
123
SetPaletteEntry(0, 191, temp0)
124
125
object.chemLiquidPalIndex1 += 3
126
object.chemLiquidPalIndex1 %= 27
127
GetTableValue(temp0, object.chemLiquidPalIndex1, EndingSetup_chemLiquidPalTable)
128
SetPaletteEntry(0, 188, temp0)
129
130
object.chemLiquidPalIndex2 += 3
131
object.chemLiquidPalIndex2 %= 27
132
GetTableValue(temp0, object.chemLiquidPalIndex2, EndingSetup_chemLiquidPalTable)
133
SetPaletteEntry(0, 189, temp0)
134
135
object.chemLiquidPalIndex3 += 3
136
object.chemLiquidPalIndex3 %= 27
137
GetTableValue(temp0, object.chemLiquidPalIndex3, EndingSetup_chemLiquidPalTable)
138
SetPaletteEntry(0, 190, temp0)
139
end if
140
141
switch object.state
142
case ENDSETUP_INIT
143
// Start off with making the clouds go really fast, to give the illusion Sonic himself is falling really fast
144
EndingSetup_scrollVelocity.x = -0x06000
145
EndingSetup_scrollVelocity.y = -0x10000
146
147
object.state = ENDSETUP_FADEINIMAGE
148
player[0].animation = ANI_FANROTATE
149
150
temp0 = 0
151
while temp0 < 256
152
// Set up palettes for the fades
153
154
// Quick palette map:
155
// > Palette ID 0 is the normal one with everything on it
156
// > Palette ID 1 is global (main-character-only)
157
// > Palette ID 2 is off-white, used when the picture slides of Tails are playing
158
// > Palette ID 3 is full white, used when Sonic's falling in the void
159
160
SetPaletteEntry(2, temp0, 0xE0E0E0)
161
SetPaletteEntry(3, temp0, 0xFFFFFF)
162
temp0++
163
loop
164
165
// Start the music!
166
PlayMusic(TRACK_STAGE)
167
168
// Check if it's the good ending
169
if specialStage.emeralds >= 0x7F
170
// Do some anti-Tails checks in case his Super form is turned off
171
// (Which it always is, meaning Tails never really gets a good ending)
172
CheckEqual(stage.playerListPos, PLAYER_TAILS_A)
173
temp0 = checkResult
174
CheckEqual(options.superTails, false)
175
temp0 &= checkResult
176
#platform: USE_ORIGINS
177
// Amy doesn't get her super form in the ending either
178
CheckEqual(stage.playerListPos, PLAYER_AMY)
179
temp0 |= checkResult
180
CheckEqual(stage.playerListPos, PLAYER_AMY_TAILS)
181
temp0 |= checkResult
182
#endplatform
183
184
if temp0 == false
185
// Make the player go Super
186
Player_superState = SUPERSTATE_SUPER
187
188
player[0].sortedDrawOrder = 5
189
190
#platform: USE_STANDALONE
191
if stage.playerListPos == PLAYER_KNUCKLES_A
192
// Knuckles gets to glide down all cool and all
193
player[0].animation = ANI_GLIDING
194
player[0].prevAnimation = ANI_GLIDING
195
player[0].frame = 2
196
else
197
// Tails gets to fly down
198
// (Though again, this doesn't get used since the variable for it is turned off)
199
player[0].animation = ANI_FLYING
200
end if
201
#endplatform
202
203
player[0].speed = 0x100000
204
player[0].invincibleTimer = 60
205
player[0].blinkTimer = 0
206
player[0].visible = true
207
player[0].rings = 0xFFFF // In case the player has their super form, this makes sure they don't lose it
208
209
switch stage.playerListPos
210
case PLAYER_SONIC_A
211
case PLAYER_SONIC_TAILS_A
212
// Super Sonic does his air run when descending
213
player[0].animation = ANI_RUNNING
214
215
// Make Super Sonic appear rather than just standard Sonic
216
arrayPos0 = stage.entityPos
217
stage.entityPos = 0
218
LoadAnimation("SuperSonic.ani")
219
stage.entityPos = arrayPos0
220
break
221
222
#platform: USE_ORIGINS
223
case PLAYER_TAILS_A
224
player[0].animation = ANI_FLYING
225
break
226
227
case PLAYER_KNUCKLES_A
228
case PLAYER_KNUCKLES_TAILS_A
229
player[0].animation = ANI_GLIDING
230
player[0].prevAnimation = ANI_GLIDING
231
player[0].frame = 2
232
break
233
234
case PLAYER_AMY_A
235
case PLAYER_AMY_TAILS_A
236
break
237
#endplatform
238
end switch
239
end if
240
end if
241
242
object.srcBlendPal = 3
243
SetPaletteFade(1, 0, object.srcBlendPal, object.blendAmount, 0, 255)
244
245
#platform: USE_STANDALONE
246
if stage.playerListPos != PLAYER_SONIC_A
247
if stage.playerListPos != PLAYER_SONIC_TAILS_A
248
// Don't display the images for other characters and make them fall for a really long time instead
249
250
// Set the active layer to space
251
stage.activeLayer[0] = 1
252
253
// And put the player up in the sky
254
player[0].xpos = 0x00D40000
255
player[0].ypos = 0x01050000
256
257
object.frame = 4
258
object.blendAmount = 976
259
object.state = ENDSETUP_ENTERPLAYER
260
end if
261
end if
262
#endplatform
263
264
#platform: USE_ORIGINS
265
// I don't really know what was wrong with how it worked before, but they changed this check
266
switch stage.playerListPos
267
case PLAYER_TAILS_A
268
case PLAYER_KNUCKLES_A
269
case PLAYER_KNUCKLES_TAILS_A
270
case PLAYER_AMY_A
271
case PLAYER_AMY_TAILS_A
272
stage.activeLayer[0] = 1
273
player[0].xpos = 0x00D40000
274
player[0].ypos = 0x01050000
275
object.frame = 4
276
object.blendAmount = 976
277
object.state = ENDSETUP_ENTERPLAYER
278
break
279
end switch
280
#endplatform
281
282
SetActivePalette(1, 0, screen.ysize)
283
break
284
285
case ENDSETUP_FADEINIMAGE
286
object.blendAmount -= 8
287
SetPaletteFade(1, 0, object.srcBlendPal, object.blendAmount, 0, 255)
288
if object.blendAmount <= 0
289
object.timer = 360
290
object.state = ENDSETUP_DISPLAYIMAGE
291
end if
292
break
293
294
case ENDSETUP_DISPLAYIMAGE
295
object.timer--
296
if object.timer == 0
297
object.state = ENDSETUP_FADEOUTIMAGE
298
if object.frame == 3
299
// Final image was just shown, use the full white palette for the fade
300
object.srcBlendPal = 3
301
else
302
// Use the off-white/grey palette
303
object.srcBlendPal = 2
304
end if
305
end if
306
break
307
308
case ENDSETUP_FADEOUTIMAGE
309
object.blendAmount += 8
310
SetPaletteFade(1, 0, object.srcBlendPal, object.blendAmount, 0, 255)
311
if object.blendAmount >= 736
312
object.frame++
313
if object.frame == 4
314
// Final image was just displayed - go on to the in-game portion of the cutscene now
315
316
// Set the active layer to space
317
stage.activeLayer[0] = 1
318
319
player[0].xpos = 0x00D40000
320
player[0].ypos = 0x01050000
321
322
object.state = ENDSETUP_ENTERPLAYER
323
else
324
// Start the next image
325
object.state = ENDSETUP_FADEINIMAGE
326
end if
327
end if
328
break
329
330
case ENDSETUP_ENTERPLAYER
331
object.blendAmount -= 8
332
temp0 = object.blendAmount
333
temp0 -= 512
334
if temp0 < 0
335
temp0 = 0
336
end if
337
338
SetPaletteFade(1, 0, object.srcBlendPal, temp0, 0, 63)
339
SetPaletteFade(1, 0, object.srcBlendPal, object.blendAmount, 64, 255)
340
341
if object.blendAmount <= 0
342
object.state = ENDSETUP_PLAYERFALLING
343
SetActivePalette(0, 0, screen.ysize)
344
end if
345
// [Fallthrough]
346
case ENDSETUP_PLAYERFALLING
347
object.tornadoTimer++
348
349
player[0].ypos += 0x10000
350
if player[0].ypos >= 0x1E00000
351
object.state = ENDSETUP_SPAWNTORNADO
352
end if
353
break
354
355
case ENDSETUP_SPAWNTORNADO
356
object.tornadoTimer++
357
object.timer--
358
if object.timer < 0
359
Rand(object.timer, 32)
360
temp0 = screen.ysize
361
temp0 += camera[0].ypos
362
temp0 += 16
363
temp0 <<= 16
364
CreateTempObject(TypeName[Cloud], 0, 0, temp0)
365
Rand(object[tempObjectPos].frame, 4)
366
if object[tempObjectPos].frame == 3
367
object[tempObjectPos].frame = 2
368
else
369
FlipSign(object[tempObjectPos].frame)
370
object[tempObjectPos].frame += 2
371
end if
372
object[tempObjectPos].drawOrder = object[tempObjectPos].frame
373
object[tempObjectPos].drawOrder++
374
375
temp0 = screen.xsize
376
Rand(object[tempObjectPos].xpos, temp0)
377
object[tempObjectPos].xpos <<= 16
378
379
temp0 = screen.ysize
380
temp0 += camera[0].ypos
381
temp0 += 16
382
temp0 <<= 16
383
CreateTempObject(TypeName[Cloud], 0, 0, temp0)
384
Rand(object[tempObjectPos].frame, 4)
385
if object[tempObjectPos].frame == 3
386
object[tempObjectPos].frame = 2
387
else
388
FlipSign(object[tempObjectPos].frame)
389
object[tempObjectPos].frame += 2
390
end if
391
392
object[tempObjectPos].drawOrder = object[tempObjectPos].frame
393
object[tempObjectPos].drawOrder++
394
395
temp0 = screen.xsize
396
Rand(object[tempObjectPos].xpos, temp0)
397
object[tempObjectPos].xpos += temp0
398
object[tempObjectPos].xpos <<= 16
399
end if
400
401
temp0 = 488
402
403
#platform: USE_STANDALONE
404
if stage.playerListPos != PLAYER_SONIC_A
405
if stage.playerListPos != PLAYER_SONIC_TAILS_A
406
// The other characters don't get special images at all, so make their timer ridiculously long
407
temp0 = 2608
408
end if
409
end if
410
#endplatform
411
412
#platform: USE_ORIGINS
413
// Again, what was wrong before?
414
switch stage.playerListPos
415
case PLAYER_TAILS_A
416
case PLAYER_KNUCKLES_A
417
case PLAYER_KNUCKLES_TAILS_A
418
case PLAYER_AMY_A
419
case PLAYER_AMY_TAILS_A
420
temp0 = 2608
421
end switch
422
#endplatform
423
424
if object.tornadoTimer == temp0
425
// Spawn the Tornado
426
427
object[33].type = TypeName[Tornado]
428
object[33].priority = PRIORITY_ACTIVE
429
430
object[33].ypos = screen.ycenter
431
object[33].ypos += camera[0].ypos
432
object[33].ypos += 21
433
434
#platform: USE_STANDALONE
435
if stage.playerListPos != PLAYER_TAILS_A
436
// Shift the Tornado a bit for other characters since they have a different hitbox than Tails
437
object[33].ypos += 4
438
end if
439
#endplatform
440
441
#platform: USE_ORIGINS
442
switch stage.playerListPos
443
case PLAYER_SONIC_A
444
case PLAYER_KNUCKLES_A
445
case PLAYER_SONIC_TAILS_A
446
case PLAYER_KNUCKLES_TAILS_A
447
object[33].ypos += 4
448
break
449
450
case PLAYER_AMY_A
451
case PLAYER_AMY_TAILS_A
452
object[33].ypos++
453
break
454
end switch
455
#endplatform
456
457
// Turn the YPos from screen-space into world-space
458
object[33].ypos <<= 16
459
460
// Although the Tornado itself doesn't use transparency, the logo rendered by it does
461
object[33].inkEffect = INK_ALPHA
462
object[33].alpha = 0
463
end if
464
465
// (Clouds are stabalized by Tornado object, not here)
466
467
if EndingSetup_scrollVelocity.y >= 0
468
object.state = ENDSETUP_TORNADOSPAWNED
469
end if
470
break
471
472
case ENDSETUP_TORNADOSPAWNED
473
object.timer--
474
if object.timer < 0
475
Rand(object.timer, 32)
476
temp0 = screen.xsize
477
temp0 += 16
478
temp0 <<= 17
479
CreateTempObject(TypeName[Cloud], 0, temp0, 0)
480
481
Rand(object[tempObjectPos].frame, 4)
482
if object[tempObjectPos].frame == 3
483
object[tempObjectPos].frame = 2
484
else
485
FlipSign(object[tempObjectPos].frame)
486
object[tempObjectPos].frame += 2
487
end if
488
489
object[tempObjectPos].drawOrder = object[tempObjectPos].frame
490
object[tempObjectPos].drawOrder++
491
object[tempObjectPos].priority = PRIORITY_ACTIVE
492
493
temp0 = screen.ysize
494
Rand(object[tempObjectPos].ypos, temp0)
495
object[tempObjectPos].ypos += camera[0].ypos
496
object[tempObjectPos].ypos -= screen.ycenter
497
object[tempObjectPos].ypos <<= 16
498
end if
499
break
500
501
end switch
502
503
// Hide the touch controls
504
options.touchControls = false
505
end event
506
507
508
event ObjectDraw
509
if object.frame < 4
510
temp0 = screen.xcenter
511
temp0 <<= 16
512
temp1 = screen.ycenter
513
temp1 <<= 16
514
DrawSpriteXY(object.frame, temp0, temp1)
515
end if
516
end event
517
518
519
event ObjectStartup
520
LoadSpriteSheet("Ending/Objects.gif")
521
522
// Ending pictures
523
SpriteFrame(-48, -36, 96, 72, 318, 1) // Animals looking up at the sky
524
SpriteFrame(-48, -36, 96, 72, 415, 1) // Tails among the crowd of animals
525
SpriteFrame(-48, -36, 96, 72, 318, 74) // Tails firing up the Tornado
526
SpriteFrame(-48, -36, 96, 72, 415, 74) // Tornado in the air with a couple of flickies in tow
527
528
SetMusicTrack("Ending.ogg", TRACK_STAGE, false)
529
530
// No badniks appear in this stage, so no freed animals should appear, either
531
// (The flickies are just spawned directly)
532
animalType1 = TypeName[Blank Object]
533
animalType2 = TypeName[Blank Object]
534
535
// Remove P2
536
player[1].type = TypeName[Blank Object]
537
playerCount = 1
538
539
// Place this object into the level and setup its values
540
object[10].type = TypeName[Ending Setup]
541
object[10].priority = PRIORITY_ACTIVE
542
object[10].chemLiquidPalIndex2 = 1
543
object[10].chemLiquidPalIndex3 = 2
544
object[10].blendAmount = 0x100
545
546
// P1 is controlled via other objects, so blank its state
547
player[0].state = Player_State_Static
548
549
#platform: USE_ORIGINS
550
if specialStage.emeralds >= 0x7F
551
CallNativeFunction2(NotifyCallback, NOTIFY_GOOD_ENDING, 0)
552
end if
553
#endplatform
554
end event
555
556
557
// ========================
558
// Editor Events
559
// ========================
560
561
event RSDKDraw
562
DrawSprite(0)
563
end event
564
565
566
event RSDKLoad
567
LoadSpriteSheet("Ending/Objects.gif")
568
SpriteFrame(-48, -36, 96, 72, 318, 1) // Ending Cutscene Image 1 - #0
569
570
SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")
571
end event
572
573