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