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