Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-1-Sonic-2-2013-Script-Decompilation
Path: blob/master/Sonic 1/Scripts/Mission/MissionWater.txt
1482 views
1
// ----------------------------------
2
// RSDK Project: Sonic 1
3
// Script Description: MissionWater Object
4
// Script Author: Christian Whitehead/Simon Thomley
5
// Unpacked by Rubberduckycooly's script unpacker
6
// ----------------------------------
7
8
// Any water objects in the scene should be followed by THREE blank objects, these manage player stuff
9
10
// ========================
11
// Aliases
12
// ========================
13
14
private alias object.value1 : object.constBubbleTimer
15
private alias object.value2 : object.randBubbleTimer
16
private alias object.value3 : object.proccessActEffects
17
private alias object.value8 : object.nextTrackID // Stores the track that should play after the drowning one stops
18
19
// Player Aliases
20
private alias object.type : player.type
21
private alias object.state : player.state
22
private alias object.xpos : player.xpos
23
private alias object.ypos : player.ypos
24
private alias object.xvel : player.xvel
25
private alias object.yvel : player.yvel
26
private alias object.speed : player.speed
27
private alias object.gravity : player.gravity
28
private alias object.animation : player.animation
29
private alias object.direction : player.direction
30
private alias object.tileCollisions : player.tileCollisions
31
private alias object.interaction : player.interaction
32
33
private alias object.value1 : player.timer
34
private alias object.value3 : player.drownTimer
35
private alias object.value4 : player.drownLevel
36
private alias object.value18 : player.sortedDrawOrder
37
private alias object.value20 : player.topSpeed
38
private alias object.value21 : player.acceleration
39
private alias object.value22 : player.deceleration
40
private alias object.value23 : player.airAcceleration
41
private alias object.value24 : player.airDeceleration
42
private alias object.value25 : player.gravityStrength
43
private alias object.value27 : player.jumpStrength
44
private alias object.value28 : player.jumpCap
45
private alias object.value37 : player.shield
46
47
// AirBubble Aliases
48
private alias object.value1 : airBubble.originPos.x
49
private alias object.value2 : airBubble.targetPlayer
50
51
// CountdownBubble Aliases
52
private alias object.value1 : countdownBubble.drawPos.x
53
private alias object.value2 : countdownBubble.drawPos.y
54
55
// Death Event Aliases
56
private alias object.value4 : object.timeOver
57
58
// Shields
59
private alias 0 : SHIELD_NONE
60
private alias 1 : SHIELD_NORMAL
61
private alias 2 : SHIELD_BUBBLE
62
private alias 3 : SHIELD_FIRE
63
private alias 4 : SHIELD_LIGHTNING
64
private alias 5 : SHIELD_GOGGLES // LZ goggles, debug mode only
65
66
// Tracks
67
private alias 0 : TRACK_STAGE
68
private alias 2 : TRACK_INVINCIBLE
69
private alias 6 : TRACK_DROWNING
70
71
// Super States
72
private alias 1 : SUPERSTATE_SUPER
73
74
75
// ========================
76
// Function Declarations
77
// ========================
78
79
reserve function MissionWater_SmallAirBubble
80
reserve function MissionWater_SpawnCountDownBubble
81
reserve function MissionWater_ResetDrownMusic
82
83
84
// ========================
85
// Static Values
86
// ========================
87
88
public value MissionWater_waterSlotID = 0
89
public value MissionWater_activateFlag = 0
90
91
92
// ========================
93
// Function Definitions
94
// ========================
95
96
private function MissionWater_SmallAirBubble
97
if object[+0].constBubbleTimer > 0
98
object[+0].constBubbleTimer--
99
100
if object[+0].randBubbleTimer > 0
101
object[+0].randBubbleTimer--
102
else
103
CreateTempObject(TypeName[Air Bubble], 2, player[0].xpos, player[0].ypos)
104
object[tempObjectPos].drawOrder = 4
105
object[tempObjectPos].yvel = -0x8800
106
airBubble[tempObjectPos].targetPlayer = 0
107
if player[0].direction == FLIP_NONE
108
object[tempObjectPos].xpos += 0x60000
109
else
110
object[tempObjectPos].xpos -= 0x60000
111
object[tempObjectPos].angle = 256
112
end if
113
airBubble[tempObjectPos].originPos.x = object[tempObjectPos].xpos
114
object[+0].randBubbleTimer = 512
115
end if
116
else
117
Rand(temp0, 3)
118
if temp0 == 1
119
Rand(object[+0].randBubbleTimer, 16)
120
object[+0].randBubbleTimer += 8
121
else
122
object[+0].randBubbleTimer = 512
123
end if
124
125
object[+0].constBubbleTimer = 60
126
CreateTempObject(TypeName[Air Bubble], 2, player[0].xpos, player[0].ypos)
127
object[tempObjectPos].drawOrder = 4
128
object[tempObjectPos].yvel = -0x8800
129
airBubble[tempObjectPos].targetPlayer = 0
130
if player[0].direction == FLIP_NONE
131
object[tempObjectPos].xpos += 0x60000
132
else
133
object[tempObjectPos].xpos -= 0x60000
134
object[tempObjectPos].angle = 256
135
end if
136
137
airBubble[tempObjectPos].originPos.x = object[tempObjectPos].xpos
138
end if
139
end function
140
141
142
private function MissionWater_SpawnCountDownBubble
143
CreateTempObject(TypeName[Countdown Bubble], temp0, player[0].xpos, player[0].ypos)
144
object[tempObjectPos].drawOrder = 5
145
object[tempObjectPos].yvel = -0x8800
146
countdownBubble[tempObjectPos].drawPos.y = 0 // this is odd... this is drawPos.y, not "targetPlayer", likely a leftover from AirBubble spawning
147
148
if player[0].direction == FLIP_NONE
149
object[tempObjectPos].xpos += 0x60000
150
else
151
object[tempObjectPos].xpos -= 0x60000
152
object[tempObjectPos].angle = 0x100
153
end if
154
155
countdownBubble[tempObjectPos].drawPos.x = object[tempObjectPos].xpos
156
end function
157
158
159
private function MissionWater_ResetDrownMusic
160
arrayPos0 = MissionWater_waterSlotID
161
arrayPos0 += 0
162
if player[0].type != TypeName[Death Event]
163
if music.currentTrack == TRACK_DROWNING
164
if object[arrayPos0].nextTrackID == TRACK_INVINCIBLE
165
arrayPos1 = 0
166
arrayPos1 += playerCount
167
if object[arrayPos1].type != TypeName[Invincibility]
168
if Player_superState != SUPERSTATE_SUPER
169
object[arrayPos0].nextTrackID = TRACK_STAGE
170
end if
171
end if
172
end if
173
174
PlayMusic(object[arrayPos0].nextTrackID)
175
end if
176
end if
177
end function
178
179
180
// ========================
181
// Events
182
// ========================
183
184
// It seems for whatever reason, Sonic Team replaced all instances of currentPlayer with 0
185
// They just found and replaced every instance with no further adjustments, so if you see "if 0 == 0" or "object[+0]" anywhere, that's why
186
187
event ObjectUpdate
188
if object.ypos < stage.newWaterLevel
189
object.ypos += 0x10000
190
end if
191
if object.ypos > stage.newWaterLevel
192
object.ypos -= 0x10000
193
end if
194
195
temp0 = oscillation
196
temp0 <<= 1
197
Sin(stage.waterLevel, temp0)
198
stage.waterLevel <<= 10
199
stage.waterLevel += object.ypos
200
temp7 = stage.waterLevel
201
stage.waterLevel >>= 16
202
203
if stage.timeEnabled == false
204
if object[0].type == TypeName[Player Object]
205
player[0].drownTimer = 0
206
end if
207
208
if object[0].type == TypeName[Death Event]
209
object[0].timeOver = 11
210
end if
211
end if
212
213
if player[0].gravityStrength == 0x3800
214
CheckNotEqual(player[0].type, TypeName[Debug Mode])
215
temp0 = checkResult
216
CheckNotEqual(player[0].state, Player_State_Death)
217
temp0 &= checkResult
218
CheckGreater(player[0].ypos, temp7)
219
temp0 &= checkResult
220
if temp0 == true
221
if player[0].yvel > 0
222
player[0].yvel >>= 2
223
end if
224
225
if object.ypos < stage.newWaterLevel
226
player[0].yvel += 0x10000
227
end if
228
229
if player[0].state == Player_State_Fly
230
StopSfx(SfxName[Flying])
231
StopSfx(SfxName[Jump])
232
end if
233
234
player[0].xvel >>= 1
235
player[0].speed >>= 1
236
237
CallFunction(Player_UpdatePhysicsState)
238
if player[0].yvel != 0
239
CreateTempObject(TypeName[Water Splash], 0, player[0].xpos, temp7)
240
object[tempObjectPos].drawOrder = 4
241
PlaySfx(SfxName[Water Splash], false)
242
end if
243
244
object[+0].constBubbleTimer = 52
245
player[0].drownTimer = 0
246
end if
247
else
248
if player[0].shield == SHIELD_FIRE
249
temp2 = 0
250
while temp2 < 8
251
Rand(temp0, 32)
252
Rand(temp1, 32)
253
temp0 -= 16
254
temp0 <<= 16
255
temp0 += player[0].xpos
256
temp1 -= 16
257
temp1 <<= 16
258
temp1 += player[0].ypos
259
CreateTempObject(TypeName[Dust Puff], 0, temp0, temp1)
260
object[tempObjectPos].drawOrder = player[0].sortedDrawOrder
261
object[tempObjectPos].drawOrder++
262
object[tempObjectPos].xvel = player[0].xvel
263
object[tempObjectPos].yvel = player[0].yvel
264
temp2++
265
loop
266
267
player[0].shield = SHIELD_NONE
268
arrayPos0 = 0
269
arrayPos0 += playerCount
270
CallFunction(Player_ApplyShield)
271
end if
272
273
if player[0].shield == SHIELD_LIGHTNING
274
player[0].shield = SHIELD_NONE
275
arrayPos0 = 0
276
arrayPos0 += playerCount
277
CallFunction(Player_ApplyShield)
278
Water_flashTimer = 4
279
end if
280
281
if player[0].shield != SHIELD_BUBBLE
282
if player[0].drownTimer == 0
283
player[0].drownLevel = 0
284
CallFunction(MissionWater_ResetDrownMusic)
285
end if
286
287
switch player[0].drownLevel
288
case 0
289
CallFunction(MissionWater_SmallAirBubble)
290
player[0].drownTimer++
291
if player[0].drownTimer == 360
292
if 0 == 0
293
PlaySfx(SfxName[Drown Alert], false)
294
end if
295
player[0].drownLevel++
296
end if
297
break
298
299
case 1
300
CallFunction(MissionWater_SmallAirBubble)
301
player[0].drownTimer++
302
if player[0].drownTimer == 660
303
if 0 == 0
304
PlaySfx(SfxName[Drown Alert], false)
305
end if
306
player[0].drownLevel++
307
end if
308
break
309
310
case 2
311
CallFunction(MissionWater_SmallAirBubble)
312
player[0].drownTimer++
313
if player[0].drownTimer == 960
314
if 0 == 0
315
PlaySfx(SfxName[Drown Alert], false)
316
end if
317
player[0].drownLevel++
318
end if
319
break
320
321
case 3
322
CallFunction(MissionWater_SmallAirBubble)
323
player[0].drownTimer++
324
if player[0].drownTimer == 1080
325
if 0 == 0
326
object.nextTrackID = music.currentTrack
327
PlayMusic(TRACK_DROWNING)
328
end if
329
330
temp0 = 0
331
CallFunction(MissionWater_SpawnCountDownBubble)
332
player[0].drownLevel++
333
end if
334
break
335
336
case 4
337
CallFunction(MissionWater_SmallAirBubble)
338
player[0].drownTimer++
339
if player[0].drownTimer == 1200
340
temp0 = 1
341
CallFunction(MissionWater_SpawnCountDownBubble)
342
player[0].drownLevel++
343
end if
344
break
345
346
case 5
347
CallFunction(MissionWater_SmallAirBubble)
348
player[0].drownTimer++
349
if player[0].drownTimer == 1320
350
temp0 = 2
351
CallFunction(MissionWater_SpawnCountDownBubble)
352
player[0].drownLevel++
353
end if
354
break
355
356
case 6
357
CallFunction(MissionWater_SmallAirBubble)
358
player[0].drownTimer++
359
if player[0].drownTimer == 1440
360
temp0 = 3
361
CallFunction(MissionWater_SpawnCountDownBubble)
362
player[0].drownLevel++
363
end if
364
break
365
366
case 7
367
CallFunction(MissionWater_SmallAirBubble)
368
player[0].drownTimer++
369
if player[0].drownTimer == 1560
370
temp0 = 4
371
CallFunction(MissionWater_SpawnCountDownBubble)
372
player[0].drownLevel++
373
end if
374
break
375
376
case 8
377
CallFunction(MissionWater_SmallAirBubble)
378
player[0].drownTimer++
379
if player[0].drownTimer == 1680
380
temp0 = 5
381
CallFunction(MissionWater_SpawnCountDownBubble)
382
player[0].drownLevel++
383
end if
384
break
385
386
case 9
387
CallFunction(MissionWater_SmallAirBubble)
388
player[0].drownTimer++
389
if player[0].drownTimer == 1800
390
if player[0].state != Player_State_Death
391
if 0 == 0
392
stage.timeEnabled = false
393
camera[0].enabled = false
394
end if
395
player[0].state = Player_State_Drown
396
player[0].animation = ANI_DROWNING
397
player[0].speed = 0
398
player[0].xvel = 0
399
player[0].yvel = 0
400
player[0].tileCollisions = false
401
player[0].interaction = false
402
player[0].sortedDrawOrder = 5
403
object[+0].constBubbleTimer = 2
404
PlaySfx(SfxName[Drowning], false)
405
player[0].drownLevel++
406
end if
407
end if
408
break
409
410
case 10
411
player[0].drownTimer++
412
if player[0].drownTimer == 1860
413
player[0].drownLevel++
414
end if
415
416
if object[+0].constBubbleTimer > 0
417
object[+0].constBubbleTimer--
418
if object[+0].randBubbleTimer > 0
419
object[+0].randBubbleTimer--
420
else
421
Rand(temp1, 2)
422
temp1 += 2
423
CreateTempObject(TypeName[Air Bubble], temp1, player[0].xpos, player[0].ypos)
424
object[tempObjectPos].drawOrder = 5
425
object[tempObjectPos].yvel = -0x8800
426
object[tempObjectPos].ypos -= 0x60000
427
airBubble[tempObjectPos].targetPlayer = 0
428
Rand(object[tempObjectPos].angle, 256)
429
airBubble[tempObjectPos].originPos.x = object[tempObjectPos].xpos
430
object[+0].randBubbleTimer = 512
431
end if
432
else
433
Rand(temp0, 5)
434
if temp0 == 1
435
object[+0].randBubbleTimer = 2
436
else
437
object[+0].randBubbleTimer = 512
438
end if
439
object[+0].constBubbleTimer = 6
440
441
Rand(temp1, 2)
442
temp1 += 2
443
CreateTempObject(TypeName[Air Bubble], temp1, player[0].xpos, player[0].ypos)
444
object[tempObjectPos].drawOrder = 5
445
object[tempObjectPos].yvel = -0x8800
446
object[tempObjectPos].ypos -= 0x60000
447
airBubble[tempObjectPos].targetPlayer = 0
448
Rand(object[tempObjectPos].angle, 0x100)
449
airBubble[tempObjectPos].originPos.x = object[tempObjectPos].xpos
450
end if
451
break
452
end switch
453
end if
454
455
CheckEqual(player[0].type, TypeName[Debug Mode])
456
temp0 = checkResult
457
CheckLower(player[0].ypos, temp7)
458
temp0 |= checkResult
459
if temp0 == true
460
if player[0].state != Player_State_Death
461
player[0].yvel <<= 1
462
if player[0].yvel < -0x100000
463
player[0].yvel = -0x100000
464
end if
465
466
// plucked this from the forever version, *this* is the water jump bug fix
467
if player[0].animation == ANI_JUMPING
468
if player[0].timer > 0
469
if player[0].yvel < -0x68000
470
player[0].yvel = -0x68000
471
end if
472
end if
473
end if
474
475
if player[0].state == Player_State_Fly
476
if player[0].timer < 480
477
PlaySfx(SfxName[Flying], true)
478
else
479
PlaySfx(SfxName[Jump], true)
480
end if
481
end if
482
483
484
CallFunction(Player_UpdatePhysicsState)
485
if player[0].yvel != 0
486
temp0 = object.ypos
487
temp0 -= player[0].ypos
488
if temp0 < 0xF00000
489
CreateTempObject(TypeName[Water Splash], 0, player[0].xpos, temp7)
490
object[tempObjectPos].drawOrder = 4
491
PlaySfx(SfxName[Water Splash], false)
492
end if
493
end if
494
495
player[0].drownTimer = 0
496
CallFunction(MissionWater_ResetDrownMusic)
497
end if
498
end if
499
end if
500
501
object.animationTimer++
502
object.animationTimer %= 24
503
object.frame = object.animationTimer
504
object.frame >>= 3
505
end event
506
507
508
event ObjectDraw
509
temp0 = screen.xoffset
510
Sin(temp1, oscillation)
511
temp1 >>= 5
512
temp0 += temp1
513
temp0 &= 63
514
FlipSign(temp0)
515
516
temp1 = stage.waterLevel
517
temp1 -= screen.yoffset
518
DrawSpriteScreenFX(object.frame, FX_INK, temp0, temp1)
519
520
temp0 += 256
521
DrawSpriteScreenFX(object.frame, FX_INK, temp0, temp1)
522
end event
523
524
525
event ObjectStartup
526
LoadSpriteSheet("LZ/Objects2.gif")
527
528
foreach (TypeName[MissionWater], arrayPos0, ALL_ENTITIES)
529
object[arrayPos0].priority = PRIORITY_ACTIVE
530
object[arrayPos0].drawOrder = 5
531
object[arrayPos0].inkEffect = INK_ALPHA
532
object[arrayPos0].alpha = 0xA0
533
stage.newWaterLevel = object[arrayPos0].ypos
534
MissionWater_waterSlotID = arrayPos0
535
stage.waterLevel = stage.newWaterLevel
536
stage.waterLevel >>= 16
537
object[arrayPos0].ypos = stage.newWaterLevel
538
next
539
540
if lampPostID > 31
541
stage.waterState = recWaterState
542
stage.waterLevel = recWaterLevel
543
stage.newWaterLevel = recWaterLevel
544
stage.newWaterLevel <<= 16
545
arrayPos0 = MissionWater_waterSlotID
546
object[arrayPos0].ypos = stage.newWaterLevel
547
else
548
stage.waterState = 0
549
end if
550
551
MissionWater_activateFlag = false
552
553
player[0].drownTimer = 0
554
if player[0].ypos > stage.newWaterLevel
555
player[0].yvel >>= 2
556
player[0].xvel >>= 1
557
player[0].speed >>= 1
558
player[0].topSpeed >>= 1
559
player[0].acceleration >>= 1
560
player[0].deceleration >>= 1
561
player[0].airAcceleration >>= 1
562
player[0].airDeceleration >>= 1
563
player[0].gravityStrength = 0x1000
564
if stage.playerListPos == PLAYER_KNUCKLES_A
565
player[0].jumpStrength = 0x30000
566
else
567
player[0].jumpStrength = 0x38000
568
end if
569
player[0].jumpCap = -0x20000
570
arrayPos0 = MissionWater_waterSlotID
571
arrayPos0 += 0 // Good job, Sonic Team
572
object[arrayPos0].constBubbleTimer = 52
573
end if
574
575
SpriteFrame(0, -8, 256, 16, 0, 129)
576
SpriteFrame(0, -8, 256, 16, 0, 146)
577
SpriteFrame(0, -8, 256, 16, 0, 163)
578
579
BrokenMonitor_ResetDrownMusic = MissionWater_ResetDrownMusic
580
end event
581
582
583
// ========================
584
// Editor Events
585
// ========================
586
587
event RSDKDraw
588
DrawSprite(0)
589
end event
590
591
592
event RSDKLoad
593
LoadSpriteSheet("LZ/Objects2.gif")
594
SpriteFrame(0, -8, 256, 16, 0, 129)
595
596
SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")
597
end event
598
599