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/Enemies/Grabber.txt
1480 views
1
// ----------------------------------
2
// RSDK Project: Sonic 2
3
// Script Description: Grabber 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.startPos.x
13
private alias object.value1 : object.startPos.y
14
private alias object.value2 : object.turnTimer
15
private alias object.value3 : object.timer
16
private alias object.value4 : object.drawingIndex
17
private alias object.value6 : object.clampFrame
18
private alias object.value7 : object.wheelFrame
19
private alias object.value8 : object.targetPlayer
20
private alias object.value9 : object.struggleDelay
21
private alias object.value10 : object.struggleTimer
22
private alias object.value11 : object.struggleFlags
23
private alias object.value12 : object.explodeTimer
24
25
// States
26
private alias 0 : GRABBER_MOVING
27
private alias 1 : GRABBER_TRYGRAB
28
private alias 2 : GRABBER_GRABDELAY
29
private alias 3 : GRABBER_MISSEDGRAB
30
private alias 4 : GRABBER_GRABBED
31
private alias 5 : GRABBER_STRUGGLE
32
private alias 6 : GRABBER_ESCAPED
33
34
// Animations
35
private alias 0 : GRABBER_ANI_IDLE
36
private alias 1 : GRABBER_ANI_OPENCLAMP
37
private alias 2 : GRABBER_ANI_GRABBED
38
39
// Player Aliases
40
private alias object.state : player.state
41
private alias object.xpos : player.xpos
42
private alias object.ypos : player.ypos
43
private alias object.xvel : player.xvel
44
private alias object.yvel : player.yvel
45
private alias object.speed : player.speed
46
private alias object.direction : player.direction
47
private alias object.gravity : player.gravity
48
private alias object.animation : player.animation
49
private alias object.left : player.left
50
private alias object.right : player.right
51
private alias object.value1 : player.timer
52
private alias object.value40 : player.hitboxLeft
53
private alias object.value38 : player.hitboxTop
54
private alias object.value41 : player.hitboxRight
55
private alias object.value39 : player.hitboxBottom
56
57
58
// ========================
59
// Function Declarations
60
// ========================
61
62
reserve function Grabber_Setup
63
reserve function Grabber_DebugDraw
64
reserve function Grabber_DebugSpawn
65
66
67
// ========================
68
// Function Definitions
69
// ========================
70
71
private function Grabber_Setup
72
object[arrayPos0].xpos = object[arrayPos0].startPos.x
73
object[arrayPos0].ypos = object[arrayPos0].startPos.y
74
object[arrayPos0].turnTimer = 256
75
object[arrayPos0].timer = 0
76
object[arrayPos0].drawingIndex = 0
77
object[arrayPos0].targetPlayer = -1
78
object[arrayPos0].struggleDelay = 0
79
object[arrayPos0].struggleTimer = 0
80
object[arrayPos0].struggleFlags = 0
81
object[arrayPos0].animation = GRABBER_ANI_IDLE
82
object[arrayPos0].state = GRABBER_MOVING
83
if object[arrayPos0].propertyValue == 0
84
object[arrayPos0].direction = FLIP_NONE
85
object[arrayPos0].xvel = -0x4000
86
else
87
object[arrayPos0].direction = FLIP_X
88
object[arrayPos0].xvel = 0x4000
89
end if
90
object[arrayPos0].priority = PRIORITY_BOUNDS
91
end function
92
93
94
private function Grabber_DebugDraw
95
temp0 = object.ypos
96
temp0 -= 0xC0000
97
DrawSpriteFX(3, FX_FLIP, object.xpos, temp0)
98
DrawSpriteFX(0, FX_FLIP, object.xpos, object.ypos)
99
DrawSpriteFX(5, FX_FLIP, object.xpos, object.ypos)
100
end function
101
102
103
private function Grabber_DebugSpawn
104
CreateTempObject(TypeName[Grabber], temp0, object.xpos, object.ypos)
105
object[tempObjectPos].startPos.x = object.xpos
106
object[tempObjectPos].startPos.y = object.ypos
107
arrayPos0 = object[tempObjectPos].entityPos
108
object[tempObjectPos].propertyValue = object.direction
109
CallFunction(Grabber_Setup)
110
end function
111
112
113
// ========================
114
// Events
115
// ========================
116
117
event ObjectUpdate
118
object.priority = PRIORITY_ACTIVE
119
switch object.state
120
case GRABBER_MOVING
121
object.turnTimer--
122
if object.turnTimer <= 0
123
object.turnTimer = 256
124
FlipSign(object.xvel)
125
object.direction ^= FLIP_X
126
end if
127
128
object.xpos += object.xvel
129
130
foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
131
BoxCollisionTest(C_TOUCH, object.entityPos, -64, 0, 64, 128, currentPlayer, 1, 1, 1, 1)
132
if checkResult == true
133
object.state = GRABBER_GRABDELAY
134
object.timer = 16
135
end if
136
next
137
break
138
139
case GRABBER_GRABDELAY
140
object.timer--
141
if object.timer < 0
142
object.timer = 32
143
object.state = GRABBER_TRYGRAB
144
object.animation = GRABBER_ANI_OPENCLAMP
145
end if
146
break
147
148
case GRABBER_TRYGRAB
149
object.timer--
150
if object.timer < 0
151
object.state = GRABBER_MISSEDGRAB
152
end if
153
154
object.ypos += 0x20000
155
break
156
157
case GRABBER_MISSEDGRAB
158
object.timer++
159
if object.timer >= 32
160
object.timer = 0
161
object.state = GRABBER_MOVING
162
object.animation = GRABBER_ANI_IDLE
163
end if
164
165
object.ypos -= 0x20000
166
break
167
168
case GRABBER_GRABBED
169
object.timer++
170
if object.timer >= 32
171
object.turnTimer = 1
172
object.timer = 16
173
object.animation = GRABBER_ANI_GRABBED
174
object.state++
175
end if
176
177
object.ypos -= 0x20000
178
currentPlayer = object.targetPlayer
179
player[currentPlayer].xpos = object.xpos
180
player[currentPlayer].ypos = object.ypos
181
player[currentPlayer].ypos += 0x100000
182
break
183
184
case GRABBER_STRUGGLE
185
if object.targetPlayer != -1
186
currentPlayer = object.targetPlayer
187
if object.struggleFlags != 0
188
object.struggleDelay--
189
if object.struggleDelay == 0
190
object.struggleTimer = 0
191
object.struggleFlags = 0
192
end if
193
194
temp0 = 0
195
if player[currentPlayer].left != false
196
temp0 |= 1
197
end if
198
199
if player[currentPlayer].right != false
200
temp0 |= 2
201
end if
202
203
if temp0 != 0
204
if temp0 != 3
205
if temp0 != object.struggleFlags
206
object.struggleFlags = temp0
207
object.struggleTimer++
208
if object.struggleTimer >= 4
209
#platform: USE_STANDALONE
210
player[currentPlayer].state = Player_State_Air
211
#endplatform
212
#platform: USE_ORIGINS
213
player[currentPlayer].state = Player_State_Air_NoDropDash
214
#endplatform
215
object.targetPlayer = -1
216
object.explodeTimer = 16
217
object.state = GRABBER_ESCAPED
218
else
219
object.struggleDelay = 32
220
end if
221
end if
222
end if
223
end if
224
else
225
if player[currentPlayer].left != false
226
object.struggleFlags |= 1
227
object.struggleDelay = 32
228
end if
229
if player[currentPlayer].right != false
230
object.struggleFlags |= 2
231
object.struggleDelay = 32
232
end if
233
end if
234
235
player[currentPlayer].xpos = object.xpos
236
player[currentPlayer].ypos = object.ypos
237
player[currentPlayer].ypos += 0x100000
238
end if
239
break
240
241
case GRABBER_ESCAPED
242
break
243
244
end switch
245
246
if object.outOfBounds == true
247
temp0 = object.xpos
248
temp1 = object.ypos
249
object.xpos = object.startPos.x
250
object.ypos = object.startPos.y
251
if object.outOfBounds == true
252
arrayPos0 = object.entityPos
253
CallFunction(Grabber_Setup)
254
else
255
object.xpos = temp0
256
object.ypos = temp1
257
end if
258
end if
259
260
if object.explodeTimer > 0
261
object.explodeTimer--
262
end if
263
264
temp7 = object.targetPlayer
265
foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
266
if currentPlayer != temp7
267
if object.targetPlayer == -1
268
if player[currentPlayer].state != Player_State_Static
269
if object.animation == GRABBER_ANI_OPENCLAMP
270
BoxCollisionTest(C_TOUCH, object.entityPos, -8, 0, 8, 16, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
271
if checkResult == true
272
object.state = GRABBER_GRABBED
273
object.animation = GRABBER_ANI_IDLE
274
object.targetPlayer = currentPlayer
275
player[currentPlayer].xvel = 0
276
player[currentPlayer].yvel = 0
277
player[currentPlayer].speed = 0
278
player[currentPlayer].timer = 0
279
player[currentPlayer].state = Player_State_Static
280
player[currentPlayer].gravity = GRAVITY_AIR
281
player[currentPlayer].animation = ANI_GRABBED
282
player[currentPlayer].direction = object.direction
283
player[currentPlayer].direction ^= FLIP_X
284
checkResult = true
285
end if
286
else
287
checkResult = false
288
end if
289
end if
290
end if
291
292
if player[currentPlayer].state != Player_State_Static
293
if object.explodeTimer == 0
294
if checkResult == false
295
BoxCollisionTest(C_TOUCH, object.entityPos, -8, -8, 8, 8, currentPlayer, player[currentPlayer].hitboxLeft, player[currentPlayer].hitboxTop, player[currentPlayer].hitboxRight, player[currentPlayer].hitboxBottom)
296
if checkResult == true
297
CallFunction(Player_BadnikBreak)
298
end if
299
end if
300
end if
301
end if
302
end if
303
next
304
305
switch object.animation
306
case GRABBER_ANI_IDLE
307
object.frame = 0
308
object.clampFrame = 5
309
GetBit(object.wheelFrame, object.turnTimer, 2)
310
object.wheelFrame += 3
311
break
312
313
case GRABBER_ANI_OPENCLAMP
314
object.animationTimer++
315
object.animationTimer &= 15
316
object.frame = object.animationTimer
317
object.frame >>= 3
318
object.clampFrame = object.frame
319
object.clampFrame += 5
320
break
321
322
case GRABBER_ANI_GRABBED
323
object.turnTimer--
324
if object.turnTimer == 0
325
if object.frame == 0
326
object.frame = 2
327
else
328
object.frame = 0
329
end if
330
331
object.turnTimer = object.timer
332
object.timer--
333
if object.timer == 0
334
if object.targetPlayer != -1
335
currentPlayer = object.targetPlayer
336
if player[currentPlayer].state == Player_State_Static
337
CallFunction(Player_Hit)
338
if player[currentPlayer].state != Player_State_GotHit
339
#platform: USE_STANDALONE
340
player[currentPlayer].state = Player_State_Air
341
#endplatform
342
#platform: USE_ORIGINS
343
player[currentPlayer].state = Player_State_Air_NoDropDash
344
#endplatform
345
end if
346
347
object.targetPlayer = -1
348
temp7 = -1
349
end if
350
end if
351
352
ResetObjectEntity(object.entityPos, TypeName[Smoke Puff], 0, object.xpos, object.ypos)
353
object.drawOrder = 4
354
PlaySfx(SfxName[Destroy], false)
355
end if
356
end if
357
break
358
359
end switch
360
361
if object.type != TypeName[Grabber]
362
if temp7 != -1
363
currentPlayer = temp7
364
#platform: USE_STANDALONE
365
player[currentPlayer].state = Player_State_Air
366
#endplatform
367
#platform: USE_ORIGINS
368
player[currentPlayer].state = Player_State_Air_NoDropDash
369
#endplatform
370
end if
371
end if
372
#platform: USE_ORIGINS
373
object.drawingIndex = 0 // Added in Origins, prevents Grabber from flickering in 2PVS Splitscreen.
374
#endplatform
375
end event
376
377
378
event ObjectDraw
379
if object.drawingIndex == 0
380
temp0 = object.startPos.y
381
temp0 -= 0x80000
382
temp1 = object.ypos
383
temp1 -= object.startPos.y
384
temp1 >>= 20
385
temp1 += 7
386
DrawSpriteFX(temp1, FX_FLIP, object.xpos, temp0)
387
temp0 -= 0x40000
388
DrawSpriteFX(object.wheelFrame, FX_FLIP, object.xpos, temp0)
389
DrawSpriteFX(object.frame, FX_FLIP, object.xpos, object.ypos)
390
AddDrawListEntityRef(5, object.entityPos)
391
else
392
DrawSpriteFX(object.clampFrame, FX_FLIP, object.xpos, object.ypos)
393
end if
394
395
object.drawingIndex ^= 1
396
end event
397
398
399
event ObjectStartup
400
// This sheet's loaded here regardless of the current stage folder, and then the proper sheet is loaded again later anyway...
401
LoadSpriteSheet("CPZ/Objects.gif")
402
403
CheckCurrentStageFolder("Zone02")
404
if checkResult == true
405
LoadSpriteSheet("CPZ/Objects.gif") // Kinda redundant for the reason up above
406
407
// Body Frames
408
SpriteFrame(-27, -8, 40, 32, 5, 74)
409
SpriteFrame(-27, -8, 43, 31, 5, 107)
410
411
// Flashing Body Frame
412
SpriteFrame(-27, -8, 40, 32, 73, 41)
413
414
// Wheel Frames
415
// They're labelled as "Unused Projectile Frames" in the S2 3.0.1 leftover dev data, but that doesn't seem like quite the right name...
416
SpriteFrame(-4, -4, 8, 8, 46, 74)
417
SpriteFrame(-4, -4, 8, 8, 114, 42)
418
419
// Front Clamp Frames
420
SpriteFrame(-6, 8, 23, 16, 5, 140)
421
SpriteFrame(-6, 8, 30, 15, 29, 140)
422
423
// String Frames
424
SpriteFrame(-1, 0, 1, 16, 2, 74)
425
SpriteFrame(-1, 0, 1, 32, 2, 74)
426
SpriteFrame(-1, 0, 1, 48, 2, 74)
427
SpriteFrame(-1, 0, 1, 64, 2, 74)
428
SpriteFrame(-1, 0, 1, 80, 2, 74)
429
SpriteFrame(-1, 0, 1, 96, 2, 74)
430
SpriteFrame(-1, 0, 1, 112, 2, 74)
431
SpriteFrame(-1, 0, 1, 128, 2, 74)
432
SpriteFrame(-1, 0, 1, 128, 2, 74)
433
SpriteFrame(0, 0, 1, 1, 1, 74)
434
else
435
LoadSpriteSheet("MBZ/Objects.gif") // Even if the CPZ sheet has been loaded, load the MBZ sheet too
436
437
// Body Frames
438
SpriteFrame(-27, -8, 40, 32, 131, 280)
439
SpriteFrame(-27, -8, 43, 31, 172, 280)
440
441
// Flashing Body Frame
442
SpriteFrame(-27, -8, 40, 32, 217, 280)
443
444
// Wheel Frames
445
// They're labelled as "Unused Projectile Frames" in the S2 3.0.1 leftover data, but that doesn't seem like quite the right name...
446
SpriteFrame(-4, -4, 8, 8, 102, 302)
447
SpriteFrame(-4, -4, 8, 8, 145, 334)
448
449
// Front Clamp Frames
450
SpriteFrame(-6, 8, 23, 16, 154, 313)
451
SpriteFrame(-6, 8, 30, 15, 178, 313)
452
453
// String Frames
454
SpriteFrame(-1, 0, 1, 16, 124, 501)
455
SpriteFrame(-1, 0, 1, 32, 124, 501)
456
SpriteFrame(-1, 0, 1, 48, 124, 501)
457
SpriteFrame(-1, 0, 1, 64, 124, 501)
458
SpriteFrame(-1, 0, 1, 80, 124, 501)
459
SpriteFrame(-1, 0, 1, 112, 124, 501)
460
SpriteFrame(-1, 0, 1, 96, 124, 501)
461
SpriteFrame(-1, 0, 1, 128, 124, 501)
462
SpriteFrame(-1, 0, 1, 128, 124, 501)
463
SpriteFrame(0, 0, 1, 1, 123, 501)
464
end if
465
466
foreach (TypeName[Grabber], arrayPos0, ALL_ENTITIES)
467
object[arrayPos0].startPos.x = object[arrayPos0].xpos
468
object[arrayPos0].startPos.y = object[arrayPos0].ypos
469
CallFunction(Grabber_Setup)
470
next
471
472
SetTableValue(TypeName[Grabber], DebugMode_ObjCount, DebugMode_TypesTable)
473
SetTableValue(Grabber_DebugDraw, DebugMode_ObjCount, DebugMode_DrawTable)
474
SetTableValue(Grabber_DebugSpawn, DebugMode_ObjCount, DebugMode_SpawnTable)
475
DebugMode_ObjCount++
476
end event
477
478
479
// ========================
480
// Editor Events
481
// ========================
482
483
event RSDKEdit
484
if editor.returnVariable == true
485
switch editor.variableID
486
case EDIT_VAR_PROPVAL // property value
487
checkResult = object.propertyValue
488
checkResult &= 1
489
break
490
491
case 0 // direction
492
GetBit(checkResult, object.propertyValue, 0)
493
break
494
495
end switch
496
else
497
switch editor.variableID
498
case EDIT_VAR_PROPVAL // property value
499
object.propertyValue = editor.variableValue
500
object.propertyValue &= 1
501
break
502
503
case 0 // direction
504
CheckNotEqual(editor.variableValue, false)
505
SetBit(object.propertyValue, 0, checkResult)
506
break
507
508
end switch
509
end if
510
end event
511
512
513
event RSDKDraw
514
if object.propertyValue == 0
515
object.direction = FLIP_NONE
516
else
517
object.direction = FLIP_X
518
end if
519
520
temp0 = object.ypos
521
temp0 -= 0xC0000
522
DrawSpriteFX(1, FX_FLIP, object.xpos, temp0)
523
DrawSpriteFX(0, FX_FLIP, object.xpos, object.ypos)
524
DrawSpriteFX(2, FX_FLIP, object.xpos, object.ypos)
525
end event
526
527
528
event RSDKLoad
529
CheckCurrentStageFolder("Zone02")
530
if checkResult == true
531
LoadSpriteSheet("CPZ/Objects.gif")
532
SpriteFrame(-27, -8, 40, 32, 5, 74)
533
SpriteFrame(-4, -4, 8, 8, 46, 74)
534
SpriteFrame(-6, 8, 23, 16, 5, 140)
535
else
536
LoadSpriteSheet("MBZ/Objects.gif")
537
SpriteFrame(-27, -8, 40, 32, 131, 280)
538
SpriteFrame(-4, -4, 8, 8, 145, 334)
539
SpriteFrame(-6, 8, 30, 15, 178, 313)
540
end if
541
542
AddEditorVariable("direction")
543
SetActiveVariable("direction")
544
AddEnumVariable("Left", 0)
545
AddEnumVariable("Right", 1)
546
end event
547
548