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/Global/ActFinish.txt
1480 views
1
// ----------------------------------
2
// RSDK Project: Sonic 2
3
// Script Description: Act Finish 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.value1 : object.textPos
14
private alias object.value2 : object.gotThroughTextPos
15
private alias object.value3 : object.timePos
16
private alias object.value4 : object.ringPos
17
private alias object.value5 : object.perfectPos
18
private alias object.value6 : object.totalPos
19
private alias object.value7 : object.timeBonus
20
private alias object.value8 : object.ringBonus
21
private alias object.value9 : object.perfectBonus
22
private alias object.value10 : object.hasPerfectBonus
23
private alias object.value11 : object.totalScore
24
private alias object.value12 : object.hasContinue // (can be Coins in Origins too)
25
26
// States
27
private alias -1 : ACTFINISH_NORESULTS
28
private alias 0 : ACTFINISH_INIT
29
private alias 1 : ACTFINISH_ENTERTEXT
30
private alias 2 : ACTFINISH_ACTFINISHJINGLE
31
private alias 3 : ACTFINISH_TALLYSCORE
32
private alias 4 : ACTFINISH_SHOWRESULTS
33
private alias 5 : ACTFINISH_LOADNEXTSTAGE
34
private alias 6 : ACTFINISH_GOTCONTINUE
35
private alias 7 : ACTFINISH_WAITFORCALLBACK
36
private alias 8 : ACTFINISH_SETSCREENFADE
37
38
// Player Aliases
39
private alias object.value0 : player.rings
40
41
// Game Modes
42
private alias 0 : MODE_NOSAVE
43
private alias 1 : MODE_SAVEGAME
44
private alias 2 : MODE_TIMEATTACK
45
46
// Achievement Aliases
47
private alias 6 : ACHIEVEMENT_PERFECTIONIST
48
49
50
// ========================
51
// Events
52
// ========================
53
54
event ObjectUpdate
55
options.touchControls = false
56
57
switch object.state
58
case ACTFINISH_INIT
59
object.drawOrder = 6
60
object.priority = PRIORITY_ACTIVE
61
object.textPos = -384
62
object.gotThroughTextPos = 384
63
object.timePos = 640
64
object.ringPos = 656
65
object.perfectPos = 672
66
object.totalPos = 688
67
68
switch stage.minutes
69
case 0
70
if stage.seconds < 30
71
object.timeBonus = 50000
72
else
73
if stage.seconds < 45
74
object.timeBonus = 10000
75
else
76
object.timeBonus = 5000
77
end if
78
end if
79
break
80
81
case 1
82
if stage.seconds < 30
83
object.timeBonus = 4000
84
else
85
object.timeBonus = 3000
86
end if
87
break
88
89
case 2
90
object.timeBonus = 2000
91
break
92
93
case 3
94
object.timeBonus = 1000
95
break
96
97
case 4
98
object.timeBonus = 500
99
break
100
101
case 5
102
object.timeBonus = 100
103
break
104
105
case 9
106
if stage.debugMode == false
107
if options.gameMode < MODE_TIMEATTACK
108
if stage.seconds == 59
109
// Cutting it really close there - give the player a ton of points
110
object.timeBonus = 100000
111
end if
112
end if
113
end if
114
break
115
116
end switch
117
118
object.ringBonus = player[0].rings
119
object.ringBonus *= 100
120
121
// Calculate Perfect Bonus
122
123
// Ring Property Values
124
// 0 = All
125
// 1 = Not needed by Sonic for perfect
126
// 2 = Not needed at all for perfect
127
128
// The tallying system seems to be a bit off, though...
129
130
switch stage.playerListPos
131
case PLAYER_SONIC_A
132
case PLAYER_SONIC_TAILS_A
133
#platform: USE_ORIGINS
134
case PLAYER_AMY_A
135
#endplatform
136
temp0 = 0
137
foreach (TypeName[Ring], arrayPos0, ALL_ENTITIES)
138
if object[arrayPos0].propertyValue <= 1 // Is this supposed to be just a `<`?
139
temp0++
140
end if
141
next
142
break
143
144
case PLAYER_TAILS_A
145
case PLAYER_KNUCKLES_A
146
temp0 = 0
147
foreach (TypeName[Ring], arrayPos0, ALL_ENTITIES)
148
if object[arrayPos0].propertyValue != 2
149
temp0++
150
end if
151
next
152
break
153
154
end switch
155
156
// Perfect Bonus
157
if temp0 == 0
158
object.hasPerfectBonus = true
159
object.perfectBonus = 50000
160
if stage.debugMode == false
161
// Grant the "Perfectionist" Achievement, for collecting all rings in a level
162
CallNativeFunction2(SetAchievement, ACHIEVEMENT_PERFECTIONIST, 100)
163
end if
164
end if
165
166
#platform: USE_STANDALONE
167
object.state++
168
#endplatform
169
170
#platform: USE_ORIGINS
171
if game.playMode == BOOT_PLAYMODE_MISSION
172
object.state = ACTFINISH_NORESULTS
173
else
174
if game.playMode == BOOT_PLAYMODE_BOSSRUSH
175
object.state = ACTFINISH_NORESULTS
176
else
177
object.state++
178
end if
179
end if
180
181
CallNativeFunction4(NotifyCallback, NOTIFY_STATS_ENEMY, StageStatsUsabilityParam1, StageStatsUsabilityParam2, StageStatsUsabilityParam3)
182
CallNativeFunction2(NotifyCallback, NOTIFY_STATS_RING, player[0].rings)
183
CallNativeFunction2(NotifyCallback, NOTIFY_ACT_FINISH, 0)
184
185
StageStatsUsabilityParam1 = 0
186
StageStatsUsabilityParam2 = 0
187
StageStatsUsabilityParam3 = 0
188
StageStatsUsabilityParam4 = 0
189
StageStatsUsabilityParam5 = 0
190
191
StatsUsabilityParam1 = 0
192
StatsUsabilityParam2 = 0
193
StatsUsabilityParam3 = 0
194
StatsUsabilityParam4 = 0
195
StatsUsabilityParam5 = 0
196
#endplatform
197
break
198
199
case ACTFINISH_ENTERTEXT
200
if object.textPos < 0
201
object.textPos += 16
202
end if
203
204
if object.gotThroughTextPos > 0
205
object.gotThroughTextPos -= 16
206
end if
207
208
if object.timePos > 0
209
object.timePos -= 16
210
end if
211
212
if object.ringPos > 0
213
object.ringPos -= 16
214
end if
215
216
if object.perfectPos > 0
217
object.perfectPos -= 16
218
end if
219
220
if object.totalPos > 0
221
object.totalPos -= 16
222
else
223
object.state++
224
end if
225
break
226
227
case ACTFINISH_ACTFINISHJINGLE
228
object.timer++
229
if object.timer > 299
230
object.timer = 0
231
object.state++
232
end if
233
break
234
235
case ACTFINISH_TALLYSCORE
236
if object.ringBonus > 0
237
object.ringBonus -= 100
238
object.totalScore += 100
239
player.score += 100
240
end if
241
242
if object.timeBonus > 0
243
object.timeBonus -= 100
244
object.totalScore += 100
245
player.score += 100
246
end if
247
248
if object.perfectBonus > 0
249
object.perfectBonus -= 100
250
object.totalScore += 100
251
player.score += 100
252
end if
253
254
CheckGreater(object.ringBonus, 0)
255
temp0 = checkResult
256
CheckGreater(object.timeBonus, 0)
257
temp0 |= checkResult
258
CheckGreater(object.perfectBonus, 0)
259
temp0 |= checkResult
260
if temp0 == true
261
object.timer++
262
if object.timer == 2
263
PlaySfx(SfxName[Score Add], false)
264
object.timer = 0
265
end if
266
else
267
if options.vsMode == false
268
if object.totalScore >= 10000
269
object.state = ACTFINISH_GOTCONTINUE
270
else
271
object.state++
272
end if
273
else
274
object.state++
275
end if
276
277
object.timer = 0
278
PlaySfx(SfxName[Score Total], false)
279
end if
280
break
281
282
case ACTFINISH_GOTCONTINUE
283
object.timer++
284
if object.timer == 60
285
object.timer = 0
286
object.hasContinue = true
287
#platform: USE_ORIGINS
288
if game.coinMode == false
289
player.continues++
290
else
291
CallNativeFunction2(NotifyCallback, NOTIFY_ADD_COIN, 3)
292
end if
293
#endplatform
294
#platform: USE_STANDALONE
295
player.continues++
296
#endplatform
297
PlaySfx(SfxName[Continue], false)
298
object.state = ACTFINISH_SHOWRESULTS
299
end if
300
break
301
302
case ACTFINISH_SHOWRESULTS
303
object.timer++
304
if object.timer == 160
305
#platform: USE_ORIGINS
306
if game.oneStageFlag != false
307
game.callbackResult = -1
308
CallNativeFunction4(NotifyCallback, NOTIFY_STAGE_RETRY, 1, stage.listPos, 0)
309
object.state = ACTFINISH_WAITFORCALLBACK
310
else
311
object.timer = 0
312
object.state++
313
end if
314
#endplatform
315
#platform: USE_STANDALONE
316
object.timer = 0
317
object.state++
318
#endplatform
319
end if
320
break
321
322
case ACTFINISH_LOADNEXTSTAGE
323
object.timer += 4
324
SetScreenFade(0, 0, 0, object.timer)
325
if object.timer == 384
326
fadeColor = 0x000000
327
object.timer = 0
328
starPostID = 0
329
330
// Huh? This object's direction doesn't really mean much, what's this supposed to mean..?
331
object.direction = FACING_RIGHT
332
333
#platform: USE_ORIGINS
334
// These following two lines were added in Origins 1.0.4
335
// RSDKv5U doesn't stop all currently playing sound effects before (re)loading a scene unlike standalone RSDKv4, so we need to stop them manually
336
StopSfx(SfxName[Flying])
337
StopSfx(SfxName[Tired])
338
#endplatform
339
340
stage.listPos++
341
342
// Hidden Palace Checks
343
if stage.listPos > 20
344
stage.listPos = 12 // Make the next stage Oil Ocean Zone Act 1
345
if options.stageSelectFlag == false
346
if stage.debugMode == false
347
if options.gameMode == MODE_NOSAVE
348
ReadSaveRAM()
349
saveRAM[46] = true // "unlockedHPZ"
350
WriteSaveRAM()
351
else
352
saveRAM[46] = true // "unlockedHPZ"
353
end if
354
end if
355
end if
356
end if
357
358
if options.gameMode == MODE_SAVEGAME
359
arrayPos1 = options.saveSlot
360
arrayPos1 <<= 3
361
if stage.player2Enabled == true
362
#platform: USE_STANDALONE
363
saveRAM[arrayPos1] = PLAYER_SONIC_TAILS_A
364
#endplatform
365
#platform: USE_ORIGINS
366
switch stage.playerListPos
367
case PLAYER_SONIC_A
368
saveRAM[arrayPos1] = PLAYER_SONIC_TAILS
369
break
370
371
case PLAYER_KNUCKLES_A
372
saveRAM[arrayPos1] = PLAYER_KNUCKLES_TAILS
373
break
374
375
case PLAYER_AMY_A
376
saveRAM[arrayPos1] = PLAYER_AMY_TAILS
377
break
378
end switch
379
#endplatform
380
else
381
saveRAM[arrayPos1] = stage.playerListPos
382
end if
383
384
arrayPos1++
385
saveRAM[arrayPos1] = player.lives
386
arrayPos1++
387
saveRAM[arrayPos1] = player.score
388
arrayPos1++
389
saveRAM[arrayPos1] = player.scoreBonus
390
arrayPos1++
391
temp0 = stage.listPos
392
temp0++
393
if temp0 > saveRAM[arrayPos1]
394
saveRAM[arrayPos1] = temp0
395
end if
396
arrayPos1++
397
saveRAM[arrayPos1] = specialStage.emeralds
398
arrayPos1++
399
saveRAM[arrayPos1] = specialStage.listPos
400
WriteSaveRAM()
401
end if
402
403
#platform: USE_ORIGINS
404
recScore = player.score
405
406
if game.oneStageFlag != false
407
stage.listPos--
408
object.state = ACTFINISH_SETSCREENFADE
409
else
410
#endplatform
411
if options.gameMode == MODE_TIMEATTACK
412
timeAttack.result = stage.seconds
413
timeAttack.result *= 100
414
temp0 = stage.minutes
415
temp0 *= 6000
416
timeAttack.result += temp0
417
timeAttack.result += stage.milliSeconds
418
stage.listPos--
419
if stage.activeList == REGULAR_STAGE
420
CallNativeFunction2(SetLeaderboard, stage.listPos, timeAttack.result)
421
else
422
// If we're on a non-regular stage, then we're in the Boss Rush so use its special ID
423
// (This was written in a pre-Origins world, before anything and everything was shoved into the BONUS_STAGE list)
424
CallNativeFunction2(SetLeaderboard, 21, timeAttack.result)
425
end if
426
427
engine.state = 8
428
else
429
temp0 = engine.trialMode
430
if stage.listPos >= stage.listSize
431
temp0 = true
432
end if
433
434
if temp0 == false
435
LoadStage()
436
else
437
stage.activeList = PRESENTATION_STAGE
438
stage.listPos = 0
439
LoadStage()
440
end if
441
end if
442
#platform: USE_ORIGINS
443
end if
444
#endplatform
445
end if
446
break
447
448
#platform: USE_ORIGINS
449
case ACTFINISH_WAITFORCALLBACK
450
if game.callbackResult >= 0
451
object.timer = 0
452
object.state = ACTFINISH_LOADNEXTSTAGE
453
end if
454
break
455
456
case ACTFINISH_SETSCREENFADE
457
SetScreenFade(0, 0, 0, 0xFF)
458
break
459
#endplatform
460
end switch
461
end event
462
463
464
event ObjectDraw
465
SetActivePalette(0, 0, screen.ysize)
466
467
temp7 = object.textPos
468
temp7 += screen.xcenter
469
470
DrawSpriteScreenXY(0, temp7, 64)
471
DrawSpriteScreenXY(1, temp7, 64)
472
473
temp7 = object.gotThroughTextPos
474
temp7 += screen.xcenter
475
DrawSpriteScreenXY(2, temp7, 82)
476
477
// Determine whether to show `got through zone` or `got through act`
478
if TitleCard_showZoneText == false
479
DrawSpriteScreenXY(3, temp7, 82)
480
temp1 = stage.actNum
481
temp1 += 4
482
DrawSpriteScreenXY(temp1, temp7, 70)
483
else
484
DrawSpriteScreenXY(4, temp7, 82)
485
end if
486
487
temp7 = object.timePos
488
temp7 += screen.xcenter
489
DrawSpriteScreenXY(8, temp7, 120)
490
DrawSpriteScreenXY(13, temp7, 120)
491
temp7 += 88
492
DrawNumbers(14, temp7, 121, object.timeBonus, 6, 8, false)
493
494
temp7 = object.ringPos
495
temp7 += screen.xcenter
496
DrawSpriteScreenXY(9, temp7, 136)
497
DrawSpriteScreenXY(13, temp7, 136)
498
temp7 += 88
499
DrawNumbers(14, temp7, 137, object.ringBonus, 5, 8, false)
500
if object.hasPerfectBonus == true
501
temp7 = object.perfectPos
502
temp7 += screen.xcenter
503
DrawSpriteScreenXY(10, temp7, 152)
504
DrawSpriteScreenXY(11, temp7, 152)
505
temp7 += 88
506
DrawNumbers(14, temp7, 153, object.perfectBonus, 5, 8, false)
507
end if
508
509
temp7 = object.totalPos
510
temp7 += screen.xcenter
511
DrawSpriteScreenXY(12, temp7, 168)
512
temp7 += 88
513
DrawNumbers(14, temp7, 169, object.totalScore, 6, 8, false)
514
515
if object.hasContinue == true
516
#platform: USE_ORIGINS
517
if game.coinMode == false
518
#endplatform
519
// Draw the Continue icon
520
GetBit(temp0, oscillation, 4)
521
if temp0 == true
522
GetBit(temp0, oscillation, 5)
523
temp0 += 24
524
temp1 = screen.xcenter
525
temp1 += 112
526
temp2 = screen.ycenter
527
temp2 += 52
528
DrawSpriteScreenXY(temp0, temp1, temp2)
529
end if
530
#platform: USE_ORIGINS
531
else
532
// Draw the Coin icon
533
534
// First, the "Coin x 3" text
535
// They could've used a constant value of 26 in the function rather than doing it this roundabout way, but if they really wanna ig
536
temp0 = 26
537
temp1 = screen.xcenter
538
temp1 += 112
539
temp2 = screen.ycenter
540
temp2 += 52
541
DrawSpriteScreenXY(temp0, temp1, temp2)
542
543
// Then, the Coins icon
544
temp0 = oscillation
545
temp0 &= 15
546
temp0 >>= 2
547
temp0 += 27
548
DrawSpriteScreenXY(temp0, temp1, temp2)
549
end if
550
#endplatform
551
end if
552
end event
553
554
555
event ObjectStartup
556
LoadSpriteSheet("Global/Display.gif")
557
558
// Assign sprite frames based on current characters in play
559
switch stage.playerListPos
560
case PLAYER_SONIC_A
561
case PLAYER_SONIC_TAILS_A
562
SpriteFrame(-64, 0, 72, 16, 1, 222) // 0 - "SONIC" large text
563
SpriteFrame(16, 0, 48, 16, 1, 205) // 1 - "GOT" large text
564
break
565
566
case PLAYER_TAILS_A
567
// Determine Miles Vs Tails
568
if options.region == false
569
SpriteFrame(-61, 0, 69, 16, 74, 222) // 0 - "TAILS" large text
570
else
571
SpriteFrame(-71, 0, 79, 16, 144, 222) // 0 - "MILES" large text
572
end if
573
SpriteFrame(16, 0, 48, 16, 1, 205) // 1 - "GOT" large text
574
break
575
576
case PLAYER_KNUCKLES_A
577
#platform: USE_ORIGINS
578
case PLAYER_KNUCKLES_TAILS_A
579
#endplatform
580
SpriteFrame(-94, 0, 128, 16, 34, 188) // 0 - "KNUCKLES" large text
581
SpriteFrame(40, 0, 48, 16, 1, 205) // 1 - "GOT" large text, note its different offset from the others
582
break
583
584
#platform: USE_ORIGINS
585
case PLAYER_AMY_A
586
case PLAYER_AMY_TAILS_A
587
SpriteFrame(-55, 0, 54, 16, 188, 239) // 0 - "AMY" large text
588
SpriteFrame(7, 0, 48, 16, 1, 205) // 1 - "GOT" large text, note its different offset from the others
589
break
590
#endplatform
591
end switch
592
593
// Frames that are the same for everyone
594
SpriteFrame(-88, 0, 112, 16, 50, 205) // 2 - "THROUGH" large text
595
SpriteFrame(33, 0, 46, 16, 163, 205) // 3 - "ACT" large text
596
SpriteFrame(33, 0, 62, 16, 83, 1) // 4 - "ZONE" large text
597
SpriteFrame(88, 0, 16, 29, 42, 1) // 5 - Act number 1
598
SpriteFrame(88, 0, 23, 29, 59, 1) // 6 - Act number 2
599
SpriteFrame(88, 0, 23, 32, 42, 31) // 7 - Act number 3
600
SpriteFrame(-91, 1, 31, 11, 2, 17) // 8 - "Time" text, cropped from normal HUD sprites
601
SpriteFrame(-92, 1, 32, 11, 1, 33) // 9 - "Rings" text, also cropped from normal HUD sprites
602
SpriteFrame(-104, 1, 56, 11, 66, 35) // 10 - "Perfect" text
603
SpriteFrame(-40, 0, 44, 16, 190, 1) // 11 - "Bonus" text
604
SpriteFrame(-71, 0, 43, 16, 146, 1) // 12 - "Total" text
605
SpriteFrame(-52, 0, 44, 16, 190, 1) // 13 - "Bonus" text, note its different offset
606
SpriteFrame(0, 0, 8, 11, 1, 50) // 14 - Number 0
607
SpriteFrame(0, 0, 8, 11, 10, 50) // 15 - Number 1
608
SpriteFrame(0, 0, 8, 11, 19, 50) // 16 - Number 2
609
SpriteFrame(0, 0, 8, 11, 28, 50) // 17 - Number 3
610
SpriteFrame(0, 0, 8, 11, 1, 62) // 18 - Number 4
611
SpriteFrame(0, 0, 8, 11, 10, 62) // 19 - Number 5
612
SpriteFrame(0, 0, 8, 11, 19, 62) // 20 - Number 6
613
SpriteFrame(0, 0, 8, 11, 28, 62) // 21 - Number 7
614
SpriteFrame(0, 0, 8, 11, 1, 74) // 22 - Number 8
615
SpriteFrame(0, 0, 8, 11, 10, 74) // 23 - Number 9
616
617
switch stage.playerListPos
618
case PLAYER_SONIC_A
619
case PLAYER_SONIC_TAILS_A
620
SpriteFrame(-8, -11, 16, 23, 178, 113) // 24 - Sonic continue frame 1
621
SpriteFrame(-8, -11, 16, 23, 195, 113) // 25 - Sonic continue frame 2
622
break
623
624
case PLAYER_TAILS_A
625
SpriteFrame(-8, -11, 16, 23, 212, 113) // 24 - Tails continue frame 1
626
SpriteFrame(-8, -11, 16, 23, 229, 113) // 25 - Tails continue frame 2
627
break
628
629
case PLAYER_KNUCKLES_A
630
#platform: USE_ORIGINS
631
case PLAYER_KNUCKLES_TAILS_A
632
#endplatform
633
SpriteFrame(-8, -11, 16, 23, 178, 137) // 24 - Knuckles continue frame 1
634
SpriteFrame(-8, -11, 16, 23, 195, 137) // 25 - Knuckles continue frame 2
635
break
636
637
#platform: USE_ORIGINS
638
case PLAYER_AMY_A
639
case PLAYER_AMY_TAILS_A
640
SpriteFrame(-8, -11, 17, 22, 212, 138) // 24 - Amy continue frame 1
641
SpriteFrame(-8, -11, 17, 22, 230, 138) // 25 - Amy continue frame 2
642
break
643
#endplatform
644
end switch
645
646
#platform: USE_ORIGINS
647
SpriteFrame(-8, -5, 50, 16, 196, 180) // 26 - Coin x 3
648
SpriteFrame(-12, -9, 24, 24, 145, 48) // 27 - Coin Sparkle 1
649
SpriteFrame(-12, -9, 24, 24, 170, 48) // 28 - Coin Sparkle 2
650
SpriteFrame(-12, -9, 24, 24, 195, 48) // 29 - Coin Sparkle 3
651
SpriteFrame(-12, -9, 24, 24, 220, 48) // 30 - Coin Sparkle 4
652
#endplatform
653
end event
654
655
656
// ========================
657
// Editor Events
658
// ========================
659
660
event RSDKDraw
661
DrawSprite(0)
662
end event
663
664
665
event RSDKLoad
666
LoadSpriteSheet("Global/Display.gif")
667
SpriteFrame(-16, -16, 32, 32, 1, 143)
668
669
SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")
670
end event
671
672