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/SignPost.txt
1479 views
1
// ----------------------------------
2
// RSDK Project: Sonic 2
3
// Script Description: Sign Post Object
4
// Script Author: Christian Whitehead/Simon Thomley
5
// Unpacked by Rubberduckycooly's script unpacker
6
// ----------------------------------
7
8
// ========================
9
// Aliases
10
// ========================
11
12
// Variables
13
private alias object.value0 : object.fallbackTimer // Added in Origins 2.0.1
14
private alias object.value1 : object.spinCount
15
private alias object.value2 : object.spinTimer
16
private alias object.value3 : object.activePlayers
17
private alias object.value4 : object.allPlayersFinished
18
private alias object.value5 : object.lastPlayerID
19
20
// States
21
private alias 0 : SIGNPOST_IDLE
22
private alias 1 : SIGNPOST_SPUN
23
private alias 2 : SIGNPOST_EXITPLAYER
24
private alias 3 : SIGNPOST_IDLE_VS
25
private alias 4 : SIGNPOST_SPUN_VS
26
private alias 5 : SIGNPOST_UNUSED // used for SBZ2>3 transition in S1, not used in this game
27
private alias 6 : SIGNPOST_FINISHED
28
29
// Player Aliases
30
private alias object.type : player.type
31
private alias object.propertyValue : player.character
32
private alias object.xpos : player.xpos
33
private alias object.ypos : player.ypos
34
private alias object.ixpos : player.ixpos
35
private alias object.speed : player.speed
36
private alias object.xvel : player.xvel
37
private alias object.yvel : player.yvel
38
private alias object.gravity : player.gravity
39
private alias object.animation : player.animation
40
private alias object.controlMode : player.controlMode
41
private alias object.scrollTracking : player.scrollTracking
42
private alias object.interaction : player.interaction
43
private alias object.jumpPress : player.jumpPress
44
private alias object.jumpHold : player.jumpHold
45
private alias object.up : player.up
46
private alias object.down : player.down
47
private alias object.left : player.left
48
private alias object.right : player.right
49
private alias object.value7 : player.invincibleTimer
50
private alias object.value21 : player.acceleration
51
private alias object.value30 : player.jumpOffset
52
53
private alias 1 : SUPERSTATE_SUPER
54
private alias 2 : SUPERSTATE_FADEOUT
55
56
// VSGame aliases
57
private alias object.value0 : vsGame.timer
58
private alias object.value5 : vsGame.countdownPlayer
59
60
// VSGame States
61
private alias 0 : VSGAME_DISPLAYTAGS
62
private alias 2 : VSGAME_FADEOUT
63
private alias 3 : VSGAME_FINISH_COUNTDOWN
64
private alias 4 : VSGAME_GOTOVSRESULTS
65
66
// Game Modes
67
private alias 2 : MODE_TIMEATTACK
68
69
// Tracks
70
private alias 1 : TRACK_ACTFINISH
71
72
// Achievement Aliases
73
private alias 0 : ACHIEVEMENT_QUICKRUN
74
private alias 3 : ACHIEVEMENT_SUPERSTAR
75
private alias 10 : ACHIEVEMENT_SCRAMBLEDEGG
76
77
// Reserved Object Slot Aliases
78
private alias 30 : SLOT_ACTFINISH
79
80
81
// ========================
82
// Function Declarations
83
// ========================
84
85
reserve function SignPost_DebugDraw
86
reserve function SignPost_DebugSpawn
87
88
89
// ========================
90
// Static Values
91
// ========================
92
93
public value SignPost_initFallback = 0
94
public value SignPost_fallbackCheck = 0
95
96
97
// ========================
98
// Function Definitions
99
// ========================
100
101
private function SignPost_DebugDraw
102
DrawSprite(0)
103
DrawSprite(1)
104
end function
105
106
107
private function SignPost_DebugSpawn
108
CreateTempObject(TypeName[Sign Post], 0, object.xpos, object.ypos)
109
object[tempObjectPos].frame = 1
110
object[tempObjectPos].spinCount = 16
111
if options.vsMode == true
112
object[tempObjectPos].state = SIGNPOST_IDLE_VS
113
end if
114
end function
115
116
117
// ========================
118
// Events
119
// ========================
120
121
event ObjectUpdate
122
switch object.state
123
case SIGNPOST_IDLE
124
#platform: USE_ORIGINS
125
object.fallbackTimer++
126
#endplatform
127
128
temp0 = object.ypos
129
temp0 += 0x400000
130
if player[0].ypos < temp0
131
stage.newXBoundary1 = object.xpos
132
stage.newXBoundary1 >>= 16
133
stage.newXBoundary1 -= screen.xcenter
134
stage.newXBoundary1 -= screen.xcenter
135
136
stage.newXBoundary2 = object.xpos
137
stage.newXBoundary2 >>= 16
138
stage.newXBoundary2 += screen.xcenter
139
140
if player[0].xpos > object.xpos
141
stage.newXBoundary1 = object.xpos
142
stage.newXBoundary1 >>= 16
143
stage.newXBoundary1 -= screen.xcenter
144
145
switch player[0].character
146
case PLAYER_SONIC_A
147
EditFrame(5, -24, -16, 48, 32, 34, 1)
148
break
149
150
case PLAYER_TAILS_A
151
EditFrame(5, -24, -16, 48, 32, 34, 34)
152
break
153
154
case PLAYER_KNUCKLES_A
155
EditFrame(5, -24, -16, 48, 32, 34, 67)
156
break
157
158
#platform: USE_ORIGINS
159
case PLAYER_AMY_A
160
EditFrame(5, -24, -16, 48, 32, 34, 149)
161
break
162
#endplatform
163
end switch
164
165
// No achievements in debug mode!
166
if stage.debugMode == false
167
if stage.activeList == BONUS_STAGE
168
// Boss Attack is on the Bonus Stage list, check for the Boss Attack achievement
169
// (This code doesn't account for Origins having everything on the Bonus list since Missions didn't even exist back then)
170
if stage.minutes < 7
171
// Grant the "Scrambled Egg" Achievement
172
CallNativeFunction2(SetAchievement, ACHIEVEMENT_SCRAMBLEDEGG, 100)
173
end if
174
else
175
if stage.listPos == 0
176
if stage.minutes == 0
177
if stage.seconds < 35
178
// Grant the "Quick Run" Achievement, for beating EHZ in under 35 seconds
179
CallNativeFunction2(SetAchievement, ACHIEVEMENT_QUICKRUN, 100)
180
end if
181
end if
182
end if
183
end if
184
end if
185
186
#platform: USE_ORIGINS
187
CallNativeFunction2(NotifyCallback, NOTIFY_TOUCH_SIGNPOST, 0)
188
#endplatform
189
stage.timeEnabled = false
190
object.state = SIGNPOST_SPUN
191
#platform: USE_ORIGINS
192
SignPost_initFallback = object.fallbackTimer
193
#endplatform
194
PlaySfx(SfxName[Sign Post], false)
195
196
if Player_superState == SUPERSTATE_SUPER
197
Player_superState = SUPERSTATE_FADEOUT
198
if stage.debugMode == false
199
// Grant the "Superstar" Achievement, for beating an act while transformed
200
CallNativeFunction2(SetAchievement, ACHIEVEMENT_SUPERSTAR, 100)
201
end if
202
end if
203
end if
204
end if
205
break
206
207
case SIGNPOST_SPUN
208
music.volume--
209
210
object.spinTimer++
211
if object.spinTimer == 2
212
object.spinTimer = 0
213
object.frame++
214
if object.frame == 5
215
object.frame = 1
216
217
Rand(temp0, 48)
218
temp0 <<= 16
219
temp0 += object.xpos
220
temp0 -= 0x180000
221
222
Rand(temp1, 32)
223
temp1 <<= 16
224
temp1 += object.ypos
225
temp1 -= 0x140000
226
227
CreateTempObject(TypeName[Ring Sparkle], 0, temp0, temp1)
228
229
object.spinCount--
230
if object.spinCount == 0
231
SetBit(object.activePlayers, 0, true)
232
if stage.player2Enabled == true
233
SetBit(object.activePlayers, 1, true)
234
end if
235
object.state = SIGNPOST_EXITPLAYER
236
end if
237
end if
238
end if
239
break
240
241
case SIGNPOST_EXITPLAYER
242
temp0 = screen.xcenter
243
temp0 <<= 16
244
temp0 += object.xpos
245
246
#platform: USE_ORIGINS
247
object.fallbackTimer++
248
SignPost_fallbackCheck = object.fallbackTimer
249
SignPost_fallbackCheck -= SignPost_initFallback
250
if SignPost_fallbackCheck > 200
251
PlayMusic(TRACK_ACTFINISH)
252
object[SLOT_ACTFINISH].type = TypeName[Act Finish]
253
object[SLOT_ACTFINISH].drawOrder = 6
254
object[SLOT_ACTFINISH].priority = PRIORITY_ACTIVE
255
end if
256
#endplatform
257
258
if player[0].xpos > temp0
259
PlayMusic(TRACK_ACTFINISH)
260
object.state = SIGNPOST_FINISHED
261
object[30].type = TypeName[Act Finish]
262
object[30].drawOrder = 6
263
object[30].priority = PRIORITY_ACTIVE
264
#platform: USE_ORIGINS
265
else
266
if player[0].animation == ANI_PUSHING
267
PlayMusic(TRACK_ACTFINISH)
268
object.state = SIGNPOST_FINISHED
269
object[30].type = TypeName[Act Finish]
270
object[30].drawOrder = 6
271
object[30].priority = PRIORITY_ACTIVE
272
end if
273
#endplatform
274
end if
275
break
276
277
case SIGNPOST_IDLE_VS
278
stage.newXBoundary2 = object.xpos
279
stage.newXBoundary2 >>= 16
280
stage.newXBoundary2 += screen.xcenter
281
foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
282
GetBit(temp1, object.activePlayers, currentPlayer)
283
if temp1 == false
284
if player[currentPlayer].xpos > object.xpos
285
object.priority = PRIORITY_ACTIVE
286
287
SetBit(object.activePlayers, currentPlayer, true)
288
289
if currentPlayer == 0
290
if Player_superState == SUPERSTATE_SUPER
291
Player_superState = SUPERSTATE_FADEOUT
292
end if
293
294
if vs.playerID == 0
295
temp2 = 0
296
else
297
temp2 = 1
298
end if
299
else
300
if vs.playerID == 0
301
temp2 = 1
302
else
303
temp2 = 0
304
end if
305
end if
306
307
if temp2 == 0
308
vs.time1P = stage.milliSeconds
309
vs.time1P = stage.seconds
310
vs.time1P *= 100
311
temp2 = stage.minutes
312
temp2 *= 6000
313
vs.time1P += temp2
314
vs.time1P += stage.milliSeconds
315
else
316
vs.time2P = stage.milliSeconds
317
vs.time2P = stage.seconds
318
vs.time2P *= 100
319
temp2 = stage.minutes
320
temp2 *= 6000
321
vs.time2P += temp2
322
vs.time2P += stage.milliSeconds
323
end if
324
325
object.lastPlayerID = currentPlayer
326
object.spinCount = 16
327
object.state = SIGNPOST_SPUN_VS
328
PlaySfx(SfxName[Sign Post], false)
329
330
if object.allPlayersFinished == false
331
PlaySfx(SfxName[Sign Post 2P], false)
332
object[30].state = VSGAME_FINISH_COUNTDOWN
333
vsGame[30].countdownPlayer = currentPlayer
334
vsGame[30].countdownPlayer ^= 1
335
switch player[currentPlayer].character
336
case PLAYER_SONIC_A
337
EditFrame(5, -24, -16, 48, 32, 34, 1)
338
break
339
340
case PLAYER_TAILS_A
341
EditFrame(5, -24, -16, 48, 32, 34, 34)
342
break
343
344
case PLAYER_KNUCKLES_A
345
EditFrame(5, -24, -16, 48, 32, 34, 67)
346
break
347
348
#platform: USE_ORIGINS
349
case PLAYER_AMY_A
350
EditFrame(5, -24, -16, 48, 32, 34, 149)
351
break
352
#endplatform
353
end switch
354
else
355
object[30].state = VSGAME_DISPLAYTAGS
356
#platform: USE_ORIGINS
357
stage.timeEnabled = false
358
#endplatform
359
end if
360
361
if object.activePlayers == 3 // both bits set? (3 is 0b11)
362
object.allPlayersFinished = true
363
object[30].state = VSGAME_DISPLAYTAGS
364
end if
365
end if
366
end if
367
next
368
break
369
370
case SIGNPOST_SPUN_VS
371
if object.allPlayersFinished == true
372
music.volume--
373
else
374
foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
375
GetBit(temp1, object.activePlayers, currentPlayer)
376
if temp1 == false
377
if player[currentPlayer].xpos > object.xpos
378
object.spinTimer = 1
379
object.frame = 4
380
object.spinCount = 1
381
end if
382
end if
383
next
384
end if
385
386
object.spinTimer++
387
if object.spinTimer == 2
388
object.spinTimer = 0
389
object.frame++
390
if object.frame == 5
391
object.frame = 1
392
Rand(temp0, 48)
393
temp0 <<= 16
394
temp0 += object.xpos
395
temp0 -= 0x180000
396
Rand(temp1, 32)
397
temp1 <<= 16
398
temp1 += object.ypos
399
temp1 -= 0x140000
400
CreateTempObject(TypeName[Ring Sparkle], 0, temp0, temp1)
401
402
object.spinCount--
403
if object.spinCount == 0
404
if object.allPlayersFinished == false
405
object.allPlayersFinished = true
406
object.state = SIGNPOST_IDLE_VS
407
408
#platform: USE_STANDALONE
409
if object.lastPlayerID == 0
410
// Start spectating P2
411
camera[0].target = 1
412
player[1].scrollTracking = true
413
object[9].type = TypeName[Blank Object]
414
CreateTempObject(TypeName[VS Game], 0, object.xpos, object.ypos)
415
vsGame[tempObjectPos].timer = 384
416
object[tempObjectPos].state = VSGAME_FADEOUT
417
camera[0].xpos = player[1].xpos
418
camera[0].xpos >>= 16
419
camera[0].ypos = player[1].ypos
420
camera[0].ypos >>= 16
421
end if
422
#endplatform
423
else
424
object.state = SIGNPOST_FINISHED
425
object[30].state = VSGAME_GOTOVSRESULTS
426
vsGame[30].timer = -768
427
end if
428
end if
429
end if
430
end if
431
break
432
433
case SIGNPOST_FINISHED
434
break
435
end switch
436
437
// Invisible off-screen barrier
438
439
// Bug Details:
440
// 212 in the line "temp0 += 212" is supposed to be the center of the screen when the screen width is set to 424 (the default screen width in RSDK)
441
// For some reason, it's set as a constant rather than using "screen.xcenter", meaning the barrier will always be 252 pixels away from the sign post regardless of screen width
442
// If your screen width is set to over 520, the barrier won't reach the edge of the screen, softlocking the game during exit stage right...
443
// We decided to provide a decomp-exclusive fix, so you shouldn't have to worry about this there
444
445
temp0 = 40
446
temp0 += 212
447
#platform: USE_DECOMP
448
temp0 = 40
449
temp0 += screen.xcenter
450
#endplatform
451
temp0 <<= 16
452
temp0 += object.xpos
453
currentPlayer = 0
454
while currentPlayer < playerCount
455
GetBit(temp1, object.activePlayers, currentPlayer)
456
if temp1 == true
457
player[currentPlayer].interaction = false
458
player[currentPlayer].controlMode = CONTROLMODE_NONE
459
player[currentPlayer].up = false
460
player[currentPlayer].down = false
461
player[currentPlayer].left = false
462
player[currentPlayer].right = true
463
player[currentPlayer].jumpPress = false
464
player[currentPlayer].jumpHold = false
465
end if
466
467
#platform: USE_DECOMP
468
// Another ultrawide screen fix, this time for when the screen is wide enough to extend beyond
469
// the stage width, causing the player to constantly fall and wrap around the stage vertically
470
temp1 = tileLayer[0].xsize
471
temp1 <<= 7
472
temp1 <<= 16
473
if player[currentPlayer].xpos > temp1
474
temp1 = object.ypos
475
temp1 += 0x200000 // This is quite a bit under the floor - this is because some acts have wavy ground at the end
476
if player[currentPlayer].animation == ANI_JUMPING
477
temp2 = player[currentPlayer].jumpOffset
478
temp2 <<= 16
479
temp1 -= temp2
480
end if
481
if player[currentPlayer].ypos > temp1
482
player[currentPlayer].ypos = temp1
483
player[currentPlayer].yvel = 0
484
end if
485
end if
486
#endplatform
487
488
if player[currentPlayer].xpos > temp0
489
player[currentPlayer].xpos = temp0
490
player[currentPlayer].speed = 0
491
player[currentPlayer].xvel = 0
492
end if
493
494
if player[currentPlayer].type == TypeName[Debug Mode]
495
SetBit(object.activePlayers, currentPlayer, false)
496
end if
497
498
currentPlayer++
499
loop
500
501
#platform: USE_ORIGINS
502
if game.playMode == BOOT_PLAYMODE_MISSION
503
if object.state > SIGNPOST_IDLE
504
player[0].invincibleTimer = 80
505
end if
506
end if
507
#endplatform
508
end event
509
510
511
event ObjectDraw
512
DrawSprite(0)
513
514
if object.spinCount > 8
515
DrawSprite(object.frame)
516
else
517
temp0 = object.frame
518
temp0 += 4
519
DrawSprite(temp0)
520
end if
521
end event
522
523
524
event ObjectStartup
525
LoadSpriteSheet("Global/Items2.gif")
526
527
SpriteFrame(-24, 16, 48, 16, 34, 132) // #0 - Post
528
529
#platform: USE_ORIGINS
530
switch stage.playerListPos
531
// Has Sonic Team never heard of a default case?
532
case PLAYER_SONIC_A
533
case PLAYER_TAILS_A
534
case PLAYER_KNUCKLES_A
535
case PLAYER_SONIC_TAILS_A
536
case PLAYER_KNUCKLES_TAILS_A
537
#endplatform
538
SpriteFrame(-24, -16, 48, 32, 34, 100) // #1 - Eggman giving a big smile
539
SpriteFrame(-16, -16, 32, 32, 149, 99) // #2 - Spin frame 1
540
SpriteFrame(-4, -16, 8, 32, 247, 2) // #3 - Spin frame 2
541
SpriteFrame(-16, -16, 32, 32, 116, 99) // #4 - Spin frame 3
542
SpriteFrame(-24, -16, 48, 32, 34, 1) // #5 - Main character frame (Sonic here, but will change to the appropriate character in-game)
543
SpriteFrame(-16, -16, 32, 32, 149, 99) // #6 - Spin frame 4 (duplicate of frame 1)
544
SpriteFrame(-4, -16, 8, 32, 247, 2) // #7 - Spin frame 5 (duplicate of frame 2)
545
SpriteFrame(-16, -16, 32, 32, 116, 99) // #8 - Spin frame 6 (duplicate of frame 3)
546
#platform: USE_ORIGINS
547
break
548
549
case PLAYER_AMY_A
550
case PLAYER_AMY_TAILS_A
551
SpriteFrame(-24, -16, 48, 32, 34, 100) // #1 - Eggman giving a big smile
552
SpriteFrame(-16, -16, 32, 32, 149, 132) // #2 - Spin frame 1 (Amy)
553
SpriteFrame(-4, -16, 8, 32, 247, 2) // #3 - Spin frame 2
554
SpriteFrame(-16, -16, 32, 32, 116, 132) // #4 - Spin frame 3 (Amy)
555
SpriteFrame(-24, -16, 48, 32, 34, 149) // #5 - Amy frame
556
SpriteFrame(-16, -16, 32, 32, 149, 132) // #6 - Spin frame 4 (duplicate of frame 1)
557
SpriteFrame(-4, -16, 8, 32, 247, 2) // #7 - Spin frame 5 (duplicate of frame 2)
558
SpriteFrame(-16, -16, 32, 32, 116, 132) // #8 - Spin frame 6 (duplicate of frame 3)
559
break
560
end switch
561
#endplatform
562
563
foreach (TypeName[Sign Post], arrayPos0, ALL_ENTITIES)
564
CheckGreater(object[arrayPos0].propertyValue, 0)
565
temp0 = checkResult
566
CheckEqual(options.vsMode, false)
567
temp0 &= checkResult
568
if temp0 == true
569
object[arrayPos0].type = TypeName[Blank Object]
570
else
571
object[arrayPos0].frame = 1
572
object[arrayPos0].spinCount = 16
573
if object[arrayPos0].propertyValue != 2
574
object[arrayPos0].priority = PRIORITY_XBOUNDS
575
end if
576
end if
577
578
if options.vsMode == true
579
object[arrayPos0].state = SIGNPOST_IDLE_VS
580
end if
581
next
582
583
SetTableValue(TypeName[Sign Post], DebugMode_ObjCount, DebugMode_TypesTable)
584
SetTableValue(SignPost_DebugDraw, DebugMode_ObjCount, DebugMode_DrawTable)
585
SetTableValue(SignPost_DebugSpawn, DebugMode_ObjCount, DebugMode_SpawnTable)
586
DebugMode_ObjCount++
587
end event
588
589
590
// ========================
591
// Editor Events
592
// ========================
593
594
event RSDKEdit
595
if editor.returnVariable == true
596
switch editor.variableID
597
case EDIT_VAR_PROPVAL // property value
598
checkResult = object.propertyValue
599
break
600
601
case 0 // type
602
checkResult = object.propertyValue
603
break
604
605
end switch
606
else
607
switch editor.variableID
608
case EDIT_VAR_PROPVAL // property value
609
object.propertyValue = editor.variableValue
610
break
611
612
case 0 // type
613
object.propertyValue = editor.variableValue
614
break
615
616
end switch
617
end if
618
end event
619
620
621
event RSDKDraw
622
DrawSprite(0)
623
DrawSprite(1)
624
end event
625
626
627
event RSDKLoad
628
LoadSpriteSheet("Global/Items2.gif")
629
SpriteFrame(-24, 16, 48, 16, 34, 132)
630
SpriteFrame(-24, -16, 48, 32, 34, 100)
631
632
AddEditorVariable("type")
633
SetActiveVariable("type")
634
AddEnumVariable("Normal", 0)
635
AddEnumVariable("VS Only (No Y Bounds)", 1)
636
AddEnumVariable("VS Only (Use Y Bounds)", 2)
637
end event
638
639